home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / vbdatabs / strdbw.cpp < prev    next >
C/C++ Source or Header  |  1999-03-28  |  127KB  |  4,207 lines

  1. // ------------------------------- //
  2. // -------- Start of File -------- //
  3. // ------------------------------- //
  4. // ----------------------------------------------------------- // 
  5. // C++ Source Code File Name: strdbw.cpp 
  6. // Compiler Used: MSVC40, HP CPP 10.24
  7. // Produced By: Doug Gaer 
  8. // File Creation Date: 12/16/1997 
  9. // Date Last Modified: 03/29/1999
  10. // Copyright (c) 1997 Douglas M. Gaer
  11. // ----------------------------------------------------------- // 
  12. // ------------- Program Description and Details ------------- // 
  13. // ----------------------------------------------------------- // 
  14. /*
  15. The VBD C++ classes are copyright (c) 1997, by Douglas M. Gaer.
  16. All those who put this code or its derivatives in a commercial
  17. product MUST mention this copyright in their documentation for
  18. users of the products in which this code or its derivative
  19. classes are used. Otherwise, you have the freedom to redistribute
  20. verbatim copies of this source code, adapt it to your specific
  21. needs, or improve the code and release your improvements to the
  22. public provided that the modified files carry prominent notices
  23. stating that you changed the files and the date of any change.
  24.  
  25. THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
  26. THE ENTIRE RISK OF THE QUALITY AND PERFORMANCE OF THIS SOFTWARE
  27. IS WITH YOU. SHOULD ANY ELEMENT OF THIS SOFTWARE PROVE DEFECTIVE,
  28. YOU WILL ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR
  29. CORRECTION.
  30.  
  31. The string database is a general-purpose object-oriented
  32. database. This version is designed to work with the wxWindow
  33. GUI library version 1.68
  34.  
  35. - Modify "dbconfig.h" file to customize the database
  36. - Modify "dbvers.h" file to uniquely identify the database
  37. - Modify "dbtcfg.h" file to customize this program
  38. - Modify "version.h" file to report changes and fixes
  39. */
  40. // ----------------------------------------------------------- //
  41. #include <stdlib.h> // Needed for getenv under HPUX CPP
  42. #include "timer.h"
  43. #include "strdbw.h"
  44. #include "strutil.h"
  45. #include "asprint.h"
  46. #include "vbdstats.h"
  47. #include "btwalker.h"
  48.  
  49. // This struct was added to read Variable Block Headers because
  50. // the Status member of VBHeader struct in the vbdfile.h file
  51. // caused a syntax error when compiling this program under HPUX
  52. // CPP version 1024. 
  53. struct VBlockHeader // (V)ariable (B)lock (H)eader 
  54. {
  55.   UINT32 CkWord;      // (C)heck (W)ord for file integrity checks (4 bytes)
  56.   UINT32 Length;      // Length of this block including VB header (4 bytes) 
  57.   UINT32 VBStatus;    // Status of dynamic data stored in VB (4 byte)
  58.   FAU NextDeletedVB;  // Pointer to next deleted VB (4 bytes) 
  59. };
  60.  
  61. // (V)ariable (B)lock (D)atabse components
  62. static POD *DB;                // Global database pointer
  63. StrDB *astrdb = 0;             // Global data buffer used to add objects
  64. StrDB *cstrdb = 0;             // Global data buffer used to change objects
  65. StrDB *dstrdb = 0;             // Global data buffer used to display objects
  66. const char *WildCard = "*";    // Used for wild card searches 
  67.  
  68. // Output limit per string for ASCII printing
  69. const int StringOffset = 15;   // Output limit per string
  70.  
  71. // Declare frame, subframe and menu objects
  72. MyFrame *frame = 0;
  73. wxMenuBar *menu_bar = 0;
  74. wxFrame *APanelFrame = 0;
  75. wxFrame *CPanelFrame = 0;
  76. wxFrame *DPanelFrame = 0;
  77.  
  78. #ifdef __USE_MSW_PRINTING__
  79. wxDialogBox *wxPageDialog = 0;  // MSW page setup dialog box
  80. MSWPrintingParameters MSWPrnPars;
  81. MSWPrintingParameters *MSWPrintSetup = &MSWPrnPars; 
  82. const int mswpDocNameLen = 255;
  83. char mswpDocumentName[mswpDocNameLen];
  84. #endif // __USE_MSW_PRINTING__
  85.  
  86. // Variable used to print display list objects
  87. int print_list = 0;
  88. int num_objects = 0;
  89. int displaying_list = 0;
  90.  
  91. // Font, Pen, and Cursor objects
  92. wxFont *labelFont = 0;
  93. wxFont *itemFont = 0;
  94. wxFont *textWindowFont = 0;
  95.  
  96. // wxWindows control objects
  97. wxButton *btn_add_add = 0;    // Object Add Panel Add button
  98. wxButton *btn_add_can = 0;    // Object Add Panel Cancel button
  99. wxButton *btn_add_close = 0;  // Object Add Panel Close button
  100. wxButton *btn_add_revert = 0; // Object Add Panel Revert button 
  101.  
  102. wxButton *btn_ch_sh = 0;     // Object Change Panel Search button
  103. wxButton *btn_ch_cm = 0;     // Object Change Panel Commit button
  104. wxButton *btn_ch_can = 0;    // Object Change Panel Cancel button
  105. wxButton *btn_ch_close = 0;  // Object Change Panel Close button
  106. wxButton *btn_ch_revert = 0; // Object Change Panel Revert button 
  107.  
  108. wxButton *btn_ds_nx = 0;     // Object Display Panel Next button
  109. wxButton *btn_ds_prev = 0;   // Object Display Panel Previous button
  110. wxButton *btn_ds_ch = 0;     // Object Display Panel Change button
  111. wxButton *btn_ds_rm = 0;     // Object Display Panel Remove button
  112. wxButton *btn_ds_close = 0;  // Object Display Panel Close button
  113.  
  114. #ifdef __USE_MSW_PRINTING__
  115. wxButton *btn_pdb_close = 0;     // MSW page setup dialog Close button
  116. wxButton *btn_pdb_cancel = 0;    // MSW page setup dialog Accept button
  117. wxButton *btn_pdb_accept = 0;    // MSW page setup dialog Accept button
  118. wxButton *btn_pdb_default = 0;   // MSW page setup dialog Default button
  119. wxSlider *LppSlider = 0;         // Lines per page slider
  120. wxSlider *CellSlider = 0;        // Cell width slider
  121. wxSlider *FsSlider = 0;          // Font size slider
  122. wxSlider *LRMSlider = 0;         // Left and right margin slider
  123. wxChoice *OrientationChoice = 0; // Orientation choice box
  124. char *OrChoiceStrings[2] = {
  125.   "Landscape",
  126.   "Portrait"
  127. };
  128.  
  129. wxChoice *FontChoice = 0;        // Font family choice box
  130. char *FontChoiceStrings[6] = {
  131.   "Swiss",      // wxSWISS
  132.   "Roman",      // wxROMAN
  133.   "Decorative", // wxDECORATIVE
  134.   "Modern",     // wxMODERN 
  135.   "Script",     // wxSCRIPT
  136.   "System"      // wxDEFAULT
  137. };
  138. #endif // __USE_MSW_PRINTING__
  139.  
  140. // This statement initializes the whole application and calls OnInit
  141. MyApp myApp;
  142.  
  143. // A macro needed for some compilers (AIX) that need 'main' to be defined
  144. // in the application itself.
  145. IMPLEMENT_WXWIN_MAIN
  146.  
  147. // `Main program' equivalent, creating windows and returning main app frame
  148. wxFrame *MyApp::OnInit(void)
  149. {
  150.   // Create the main frame window
  151.   frame = new MyFrame(NULL, (char *)ProgramName, 50, 50, 400, 300);
  152.  
  153.   // Give this frame a status line
  154.   frame->CreateStatusLine(1);
  155.   
  156.   // Give it an icon
  157. #ifdef wx_msw
  158.   frame->SetIcon(new wxIcon("vbdbase"));
  159. #endif
  160. #ifdef wx_x
  161.   frame->SetIcon(new wxIcon("vbdbase.xbm"));
  162. #endif
  163.  
  164.   // File menu 
  165.   wxMenu *file_menu = new wxMenu;
  166.   file_menu->Append(FILE_VBDSTATS, "VBD file Stats", 
  167.             "Display VBD file statistics");
  168.   file_menu->AppendSeparator();
  169.   file_menu->Append(FILE_EXPORT, "Export","Export database to ASCII file");
  170.   file_menu->Append(FILE_IMPORT, "Import", "Import ASCII file into database");
  171.   file_menu->Append(FILE_TEMPLATE, "Create Template",
  172.             "Create an ASCII template for import file");
  173.   file_menu->AppendSeparator();
  174.   file_menu->Append(FILE_BACKUP, "Backup",
  175.             "Backup the database to another file");
  176.   file_menu->Append(FILE_MERGE, "Merge",
  177.             "Merge the contents of another database file");
  178.   file_menu->AppendSeparator();
  179.   file_menu->Append(FILE_COMPARE_INDEX, "Compare Index File",
  180.             "Compare the index file to the database file");
  181.  
  182.   file_menu->Append(FILE_REBUILD_INDEX, "Rebuild Index File",
  183.             "Rebuild the index file for this database");
  184.   file_menu->AppendSeparator();
  185.   file_menu->Append(FILE_QUIT, "E&xit","Exit this program");
  186.  
  187.   // Edit menu
  188.   wxMenu *edit_menu = new wxMenu;
  189.   edit_menu->Append(EDIT_CUT, "Cut\tCtrl+X", "Cut text and copy to clipboard");
  190.   edit_menu->AppendSeparator();
  191.   edit_menu->Append(EDIT_COPY, "Copy\tCtrl+C", "Copy text to clipboard");
  192.   edit_menu->AppendSeparator();
  193.   edit_menu->Append(EDIT_PASTE, "Paste\tCtrl+V", "Paste text from clipboard");
  194.   
  195.   // Database menu
  196.   wxMenu *db_menu = new wxMenu;
  197.   db_menu->Append(DB_DISPLAY, "&Display", "Display all objects one a time");
  198.   db_menu->AppendSeparator();
  199.   db_menu->Append(DB_ADD, "&Add", "Add objects to the database");
  200.   db_menu->AppendSeparator();
  201.   db_menu->Append(DB_CHANGE, "&Change", "Change an object in the database");
  202.   db_menu->AppendSeparator();
  203.   db_menu->Append(DB_REMOVE, "&Remove", "Remove an object from the database");
  204.   
  205.   // Find menu
  206.   wxMenu *find_menu = new wxMenu;
  207.   find_menu->AppendSeparator();
  208.   const char *Prompt = "Find by ";
  209.   UString s(Prompt); int PromptLen = strlen(Prompt); int StringLen = 0;
  210.   if(KeyName != 0) {
  211.     s = s + KeyName; StringLen = strlen(KeyName);
  212.     find_menu->Append(FIND_BYKEYNAME, s.c_str(), s.c_str());
  213.     find_menu->AppendSeparator();
  214.     s.DeleteAt(PromptLen, StringLen);
  215.   }
  216.   if(M2Name != 0) {
  217.     s = s + M2Name; StringLen = strlen(M2Name);
  218.     find_menu->Append(FIND_BYM2NAME, s.c_str(), s.c_str());
  219.     find_menu->AppendSeparator();
  220.     s.DeleteAt(PromptLen, StringLen);
  221.   }
  222.   if(M3Name != 0) {
  223.     s = s + M3Name; StringLen = strlen(M3Name);
  224.     find_menu->Append(FIND_BYM3NAME, s.c_str(), s.c_str());
  225.     find_menu->AppendSeparator();
  226.     s.DeleteAt(PromptLen, StringLen);
  227.   }
  228.   if(M4Name != 0) {
  229.     s = s + M4Name; StringLen = strlen(M4Name);
  230.     find_menu->Append(FIND_BYM4NAME, s.c_str(), s.c_str());
  231.     find_menu->AppendSeparator();
  232.     s.DeleteAt(PromptLen, StringLen);
  233.   }
  234.   if(M5Name != 0) {
  235.     s = s + M5Name; StringLen = strlen(M5Name);
  236.     find_menu->Append(FIND_BYM5NAME, s.c_str(), s.c_str());
  237.     find_menu->AppendSeparator();
  238.     s.DeleteAt(PromptLen, StringLen);
  239.   }
  240.   if(M6Name != 0) {
  241.     s = s + M6Name; StringLen = strlen(M6Name);
  242.     find_menu->Append(FIND_BYM6NAME, s.c_str(), s.c_str());
  243.     find_menu->AppendSeparator();
  244.     s.DeleteAt(PromptLen, StringLen);
  245.   }
  246.   if(M7Name != 0) {
  247.     s = s + M7Name; StringLen = strlen(M7Name);
  248.     find_menu->Append(FIND_BYM7NAME, s.c_str(), s.c_str());
  249.     find_menu->AppendSeparator();
  250.     s.DeleteAt(PromptLen, StringLen);
  251.   }
  252.   if(M8Name != 0) {
  253.     s = s + M8Name; StringLen = strlen(M8Name);
  254.     find_menu->Append(FIND_BYM8NAME, s.c_str(), s.c_str());
  255.     find_menu->AppendSeparator();
  256.     s.DeleteAt(PromptLen, StringLen);
  257.   }
  258.   if(Comments != 0) {
  259.     s = s + Comments; StringLen = strlen(Comments);
  260.     find_menu->Append(FIND_BYCOMMENTS, s.c_str(), s.c_str());
  261.     find_menu->AppendSeparator();
  262.     s.DeleteAt(PromptLen, StringLen);
  263.   }
  264.  
  265.   // Print menu
  266.   wxMenu *print_menu = new wxMenu;
  267. #ifdef __USE_MSW_PRINTING__
  268.   print_menu->Append(WXPRINT_PRINT, "Print...",
  269.              "Print to the selected printer");
  270.   print_menu->Append(WXPRINT_PRINTER_SETUP, "Printer Setup...",
  271.              "Configure the seleted printer");
  272.   print_menu->Append(WXPRINT_PAGE_SETUP, "Page Setup...",
  273.              "Set the page parameters before printing");
  274.   print_menu->Append(WXPRINT_PREVIEW, "Print Preview",
  275.              "Preview before printing");
  276.   print_menu->AppendSeparator();
  277. #endif // __USE_MSW_PRINTING__
  278.   print_menu->Append(PRINT_POSTSCRIPT, "Print to PostScript file",
  279.              "Print database to a PostScript file");
  280.   print_menu->AppendSeparator();
  281.   print_menu->Append(PRINT_HTML, "Print to HTML file",
  282.              "Print database to an HTML file");
  283.   print_menu->AppendSeparator();
  284.   print_menu->Append(PRINT_ASCIIALL, "Print to text file 80 cols",
  285.              "Print to text file (abbreviated,  80 cols)");
  286.   print_menu->Append(PRINT_ASCIILONG, "Print to text file 132 cols",
  287.              "Print to text file (full listing, 132 cols)");
  288.   print_menu->AppendSeparator();
  289.   print_menu->Append(PRINT_ASCIIOBJECT, "Print object to text file",
  290.              "Print a single object to a text file");
  291.   
  292.   // View menu
  293.   wxMenu *view_menu = new wxMenu;
  294.   view_menu->Append(VIEW_CLEAR, "&Clear Window", "Clear this text window");
  295.   
  296.   // Help menu
  297.   wxMenu *help_menu = new wxMenu;
  298.   help_menu->Append(HELP_ABOUT, "&About", "Info about this program");
  299.   help_menu->AppendSeparator();
  300.   help_menu->Append(HELP_USERLEVEL, "Access Rights",
  301.             "Display your user access rights");
  302.   
  303.   // Make all the menu bars  
  304.   menu_bar = new wxMenuBar;
  305.   menu_bar->Append(file_menu, "&File");
  306.   menu_bar->Append(edit_menu, "&Edit");
  307.   menu_bar->Append(db_menu, "Data&base");
  308.   menu_bar->Append(find_menu, "F&ind");
  309.   menu_bar->Append(print_menu, "&Print");
  310.   menu_bar->Append(view_menu, "&View");
  311.   menu_bar->Append(help_menu, "&Help");
  312.   frame->SetMenuBar(menu_bar);
  313.  
  314.   // Associate the menu bar with the frame
  315.   frame->SetMenuBar(menu_bar);
  316.  
  317.   // Create a text window in the main frame
  318.   frame->textWin = new MyTextWindow(frame, 0, 250, 400, 250,
  319.                     wxNATIVE_IMPL);
  320.   frame->textWin->DragAcceptFiles(TRUE);
  321.   
  322. // *********************************************************** //
  323. // Object Add Panel Code Starts Here 
  324. // *********************************************************** //
  325.   frame->addText = new MyText; // Init MyText Class pointer
  326.   APanelFrame = new wxFrame(NULL, "Adding Object", 0, 0, 370, 370);
  327.  
  328.   // Panel fonts
  329.   labelFont = new wxFont(12, wxSWISS, wxNORMAL, wxBOLD);
  330.   itemFont = new wxFont(11, wxSWISS, wxNORMAL, wxBOLD);
  331.  
  332.   // Give it an icon
  333. #ifdef wx_msw
  334.   APanelFrame->SetIcon(new wxIcon("vbdbase"));
  335. #endif
  336. #ifdef wx_x
  337.   APanelFrame->SetIcon(new wxIcon("vbdbase.xbm"));
  338. #endif
  339.  
  340.   int apfwidth, apfheight;
  341.   APanelFrame->GetClientSize(&apfwidth, &apfheight);
  342.  
  343.   // Make a panel in the subframe
  344.   frame->apanel = new wxPanel(APanelFrame, 0, 0,
  345.                   apfwidth, apfheight); 
  346.   frame->apanel->SetLabelPosition(wxVERTICAL);
  347.   frame->apanel->SetLabelFont(labelFont);
  348.   frame->apanel->SetButtonFont(itemFont);
  349.   frame->apanel->SetFont(itemFont);
  350.  
  351.   // Needed to line up first addText box under motif 
  352.   frame->apanel->NewLine(); 
  353.  
  354.   if(KeyName != 0)
  355.     frame->addText->key = new wxText(frame->apanel, NULL,
  356.                     (char *)KeyName, "",-1,-1,150,-1); 
  357.   frame->apanel->NewLine();
  358.   if(M2Name != 0) 
  359.     frame->addText->m2 = new wxText(frame->apanel, (wxFunction)&text_proc,
  360.                        (char *)M2Name, "", -1, -1, 150, -1);
  361.   if(M3Name != 0) 
  362.     frame->addText->m3 = new wxText(frame->apanel, (wxFunction)&text_proc,
  363.                        (char *)M3Name, "", -1, -1, 150, -1);
  364.   frame->apanel->NewLine();
  365.   if(M4Name != 0) 
  366.     frame->addText->m4 = new wxText(frame->apanel, (wxFunction)&text_proc,
  367.                      (char *)M4Name, "", -1, -1, 150, -1);
  368.   if(M5Name != 0) 
  369.     frame->addText->m5 = new wxText(frame->apanel, (wxFunction)&text_proc,
  370.                        (char *)M5Name, "", -1, -1, 150, -1); 
  371.   frame->apanel->NewLine();
  372.   if(M6Name != 0) 
  373.     frame->addText->m6 = new wxText(frame->apanel, (wxFunction)&text_proc,
  374.                        (char *)M6Name, "", -1, -1, 150, -1);
  375.   if(M7Name != 0) 
  376.     frame->addText->m7 = new wxText(frame->apanel, (wxFunction)&text_proc,
  377.                        (char *)M7Name, "", -1, -1, 150, -1);
  378.   frame->apanel->NewLine();
  379.   if(M8Name != 0) 
  380.     frame->addText->m8 = new wxText(frame->apanel, (wxFunction)&text_proc,
  381.                      (char *)M8Name, "", -1, -1, 150, -1);
  382.   if(Comments != 0) 
  383.     frame->addText->cmt = new wxText(frame->apanel, (wxFunction)&text_proc,
  384.                     (char *)Comments, "", -1, -1, 150, -1);
  385.   frame->apanel->NewLine();
  386.   
  387.   btn_add_add = new wxButton(frame->apanel, (wxFunction)&AddBtnProc, "Add");
  388.   btn_add_add->SetClientData((char*)ADD_BUTTON_ADD); // ID the button  
  389.  
  390.   btn_add_can = new wxButton(frame->apanel,(wxFunction)&AddBtnProc, "Cancel");
  391.   btn_add_can->SetClientData((char*)ADD_BUTTON_CANCEL); // ID the button  
  392.  
  393.   btn_add_close = new wxButton(frame->apanel, (wxFunction)&AddBtnProc,
  394.                    "Close");
  395.   btn_add_close->SetClientData((char*)ADD_BUTTON_CLOSE); // ID the button  
  396.  
  397.   btn_add_revert = new wxButton(frame->apanel, (wxFunction)&AddBtnProc,
  398.                 "Revert");
  399.   btn_add_revert->SetClientData((char*)ADD_BUTTON_REVERT); // ID the button  
  400.  
  401. // *********************************************************** //
  402. // Object Add Panel Code Ends Here 
  403. // *********************************************************** //
  404.  
  405. // *********************************************************** //
  406. // Object Change Panel Code Starts Here 
  407. // *********************************************************** //
  408.   frame->changeText = new MyText; // Init MyText Class pointer
  409.   CPanelFrame = new wxFrame(NULL, "Changing Object", 0, 0, 400, 390);
  410.  
  411.   // Give it an icon
  412. #ifdef wx_msw
  413.   CPanelFrame->SetIcon(new wxIcon("vbdbase"));
  414. #endif
  415. #ifdef wx_x
  416.   CPanelFrame->SetIcon(new wxIcon("vbdbase.xbm"));
  417. #endif
  418.  
  419.   int cpfwidth, cpfheight;
  420.   CPanelFrame->GetClientSize(&cpfwidth, &cpfheight);
  421.  
  422.   // Make a panel in the subframe
  423.   frame->cpanel = new wxPanel(CPanelFrame, 0, 0,
  424.                   cpfwidth, cpfheight);
  425.   frame->cpanel->SetLabelPosition(wxVERTICAL);
  426.   frame->cpanel->SetLabelFont(labelFont);
  427.   frame->cpanel->SetButtonFont(itemFont);
  428.   frame->cpanel->SetFont(itemFont);
  429.  
  430.   // Needed to line up first panel with the others under motif 
  431.   frame->cpanel->NewLine(); 
  432.  
  433.   UString cmesg("Enter the ");
  434.   cmesg = cmesg + KeyName + " and click on Search.";
  435.   wxMessage *message = new wxMessage(frame->cpanel, cmesg.c_str());
  436.   frame->cpanel->NewLine();
  437.   
  438.   if(KeyName != 0)
  439.     frame->changeText->key = new wxText(frame->cpanel, NULL,
  440.                     (char *)KeyName, "",-1,-1,150,-1); 
  441.   frame->cpanel->NewLine();
  442.   if(M2Name != 0) 
  443.     frame->changeText->m2 = new wxText(frame->cpanel, (wxFunction)&text_proc,
  444.                        (char *)M2Name, "", -1, -1, 150, -1);
  445.   if(M3Name != 0) 
  446.     frame->changeText->m3 = new wxText(frame->cpanel, (wxFunction)&text_proc,
  447.                        (char *)M3Name, "", -1, -1, 150, -1);
  448.   frame->cpanel->NewLine();
  449.   if(M4Name != 0) 
  450.     frame->changeText->m4 = new wxText(frame->cpanel, (wxFunction)&text_proc,
  451.                      (char *)M4Name, "", -1, -1, 150, -1);
  452.   if(M5Name != 0) 
  453.     frame->changeText->m5 = new wxText(frame->cpanel, (wxFunction)&text_proc,
  454.                        (char *)M5Name, "", -1, -1, 150, -1); 
  455.   frame->cpanel->NewLine();
  456.   if(M6Name != 0) 
  457.     frame->changeText->m6 = new wxText(frame->cpanel, (wxFunction)&text_proc,
  458.                        (char *)M6Name, "", -1, -1, 150, -1);
  459.   if(M7Name != 0) 
  460.     frame->changeText->m7 = new wxText(frame->cpanel, (wxFunction)&text_proc,
  461.                        (char *)M7Name, "", -1, -1, 150, -1);
  462.   frame->cpanel->NewLine();
  463.   if(M8Name != 0) 
  464.     frame->changeText->m8 = new wxText(frame->cpanel, (wxFunction)&text_proc,
  465.                      (char *)M8Name, "", -1, -1, 150, -1);
  466.   if(Comments != 0) 
  467.     frame->changeText->cmt = new wxText(frame->cpanel, (wxFunction)&text_proc,
  468.                     (char *)Comments, "", -1, -1, 150, -1);
  469.   frame->cpanel->NewLine();
  470.   
  471.   btn_ch_sh = new wxButton(frame->cpanel, (wxFunction)&ChBtnProc, "Search");
  472.   btn_ch_sh->SetClientData((char*)CHANGE_BUTTON_SH); // ID the button  
  473.  
  474.   btn_ch_cm = new wxButton(frame->cpanel, (wxFunction)&ChBtnProc, "Commit");
  475.   btn_ch_cm->SetClientData((char*)CHANGE_BUTTON_CM); // ID the button  
  476.   btn_ch_cm->Enable(0);
  477.   
  478.   btn_ch_can = new wxButton(frame->cpanel,(wxFunction)&ChBtnProc, "Cancel");
  479.   btn_ch_can->SetClientData((char*)CHANGE_BUTTON_CANCEL); // ID the button  
  480.  
  481.   btn_ch_close = new wxButton(frame->cpanel, (wxFunction)&ChBtnProc, "Close");
  482.   btn_ch_close->SetClientData((char*)CHANGE_BUTTON_CLOSE); // ID the button  
  483.  
  484.   btn_ch_revert = new wxButton(frame->cpanel, (wxFunction)&ChBtnProc,
  485.                 "Revert");
  486.   btn_ch_revert->SetClientData((char*)CHANGE_BUTTON_REVERT); // ID the button  
  487. // *********************************************************** //
  488. // Object Change Panel Code Ends Here 
  489. // *********************************************************** //
  490.  
  491. // *********************************************************** //
  492. // Object Display Panel Code Starts Here 
  493. // *********************************************************** //
  494.   frame->displayText = new MyText; // Init MyText Class pointer
  495.   DPanelFrame = new wxFrame(NULL, "Displaying Objects", 0, 0,
  496.                 370, 370);
  497.  
  498.   // Give it an icon
  499. #ifdef wx_msw
  500.   DPanelFrame->SetIcon(new wxIcon("vbdbase"));
  501. #endif
  502. #ifdef wx_x
  503.   DPanelFrame->SetIcon(new wxIcon("vbdbase.xbm"));
  504. #endif
  505.  
  506.   int dpfwidth, dpfheight;
  507.   DPanelFrame->GetClientSize(&dpfwidth, &dpfheight);
  508.  
  509.   // Make a panel in the subframe
  510.   frame->dpanel = new wxPanel(DPanelFrame, 0, 0,
  511.                   dpfwidth, dpfheight);
  512.   frame->dpanel->SetLabelPosition(wxVERTICAL);
  513.   frame->dpanel->SetLabelFont(labelFont);
  514.   frame->dpanel->SetButtonFont(itemFont);
  515.   frame->dpanel->SetFont(itemFont);
  516.  
  517.   // Needed to line up first addText box under motif 
  518.   frame->dpanel->NewLine(); 
  519.  
  520.   if(KeyName != 0) {
  521.     frame->displayText->key = new wxText(frame->dpanel, NULL,
  522.                     (char *)KeyName, "",-1,-1,150,-1);
  523.     frame->displayText->key->SetEditable(FALSE);
  524.   }
  525.  
  526.   frame->dpanel->NewLine();
  527.  
  528.   if(M2Name != 0) { 
  529.     frame->displayText->m2 = new wxText(frame->dpanel, (wxFunction)&text_proc,
  530.                        (char *)M2Name, "", -1, -1, 150, -1);
  531.     frame->displayText->m2->SetEditable(FALSE);
  532.   }
  533.   
  534.   if(M3Name != 0) {
  535.     frame->displayText->m3 = new wxText(frame->dpanel, (wxFunction)&text_proc,
  536.                        (char *)M3Name, "", -1, -1, 150, -1);
  537.     frame->displayText->m3->SetEditable(FALSE);
  538.   }
  539.  
  540.   frame->dpanel->NewLine();
  541.  
  542.   if(M4Name != 0) {
  543.     frame->displayText->m4 = new wxText(frame->dpanel, (wxFunction)&text_proc,
  544.                      (char *)M4Name, "", -1, -1, 150, -1);
  545.     frame->displayText->m4->SetEditable(FALSE);
  546.   }
  547.   if(M5Name != 0) {
  548.     frame->displayText->m5 = new wxText(frame->dpanel, (wxFunction)&text_proc,
  549.                        (char *)M5Name, "", -1, -1, 150, -1);
  550.     frame->displayText->m5->SetEditable(FALSE);
  551.   }
  552.   
  553.   frame->dpanel->NewLine();
  554.   
  555.   if(M6Name != 0) {
  556.     frame->displayText->m6 = new wxText(frame->dpanel, (wxFunction)&text_proc,
  557.                        (char *)M6Name, "", -1, -1, 150, -1);
  558.     frame->displayText->m6->SetEditable(FALSE);
  559.   }
  560.   
  561.   if(M7Name != 0) {
  562.     frame->displayText->m7 = new wxText(frame->dpanel, (wxFunction)&text_proc,
  563.                        (char *)M7Name, "", -1, -1, 150, -1);
  564.     frame->displayText->m7->SetEditable(FALSE);
  565.   }
  566.  
  567.   frame->dpanel->NewLine();
  568.  
  569.   if(M8Name != 0) {
  570.     frame->displayText->m8 = new wxText(frame->dpanel, (wxFunction)&text_proc,
  571.                      (char *)M8Name, "", -1, -1, 150, -1);
  572.     frame->displayText->m8->SetEditable(FALSE);
  573.   }
  574.   
  575.   if(Comments != 0) {
  576.     frame->displayText->cmt = new wxText(frame->dpanel, (wxFunction)&text_proc,
  577.                     (char *)Comments, "", -1, -1, 150, -1);
  578.     frame->displayText->cmt->SetEditable(FALSE);
  579.   }
  580.   
  581.   frame->dpanel->NewLine();
  582.   frame->dpanel->NewLine();
  583.   
  584.   btn_ds_nx = new wxButton(frame->dpanel, (wxFunction)&DsBtnProc, "Next");
  585.   btn_ds_nx->SetClientData((char*)DISPLAY_BUTTON_NX); // ID the button  
  586.   
  587.   btn_ds_prev = new wxButton(frame->dpanel, (wxFunction)&DsBtnProc, "Prior");
  588.   btn_ds_prev->SetClientData((char*)DISPLAY_BUTTON_PREV); // ID the button  
  589.  
  590.   btn_ds_ch = new wxButton(frame->dpanel,(wxFunction)&DsBtnProc, "Change");
  591.   btn_ds_ch->SetClientData((char*)DISPLAY_BUTTON_CHANGE); // ID the button  
  592.  
  593.   btn_ds_close = new wxButton(frame->dpanel, (wxFunction)&DsBtnProc, "Close");
  594.   btn_ds_close->SetClientData((char*)DISPLAY_BUTTON_CLOSE); // ID the button  
  595.  
  596.   btn_ds_rm = new wxButton(frame->dpanel, (wxFunction)&DsBtnProc, "Remove");
  597.   btn_ds_rm->SetClientData((char*)DISPLAY_BUTTON_REMOVE); // ID the button
  598. // *********************************************************** //
  599. // Object Display Panel Code Ends Here 
  600. // *********************************************************** //
  601.  
  602.   // Show the frames
  603.   frame->Show(TRUE);
  604.   APanelFrame->Show(FALSE);
  605.   CPanelFrame->Show(FALSE);
  606.   displaying_list = 0;
  607.   DPanelFrame->Show(FALSE);
  608.   
  609.   // Vaiable Block Database components
  610.   char *FileName = 0;
  611.   char *CurrentCfgFile = 0;
  612.   char *CfgFile = 0;
  613.   Config *CfgData = new Config;
  614.   char *AdminUser = 0;
  615.   const char *DefaultWelcomeMesg = "welcome.txt";
  616.   char *WelcomeMesgFile = 0;
  617.   
  618. #ifdef __USE_MSW_PRINTING__
  619.   // Default values for wxWindows MSW Printing
  620.   int mswp_lines_per_page = 0;
  621.   int mswp_cell_length = 0;
  622.   int mswp_font_size = 0;
  623.   int mswp_left_margin = 0;
  624.   char *mswp_orientation = 0;
  625.   char *mswp_doc_name = 0;
  626.   char *mswp_font = 0;
  627. #endif // __USE_MSW_PRINTING__
  628.   
  629.   // Look for CfgFile name in environment
  630.   if((CurrentCfgFile = getenv(EnvSetting)) == 0)
  631.      CfgFile = (char *)DefaultCfgFile;
  632.   else
  633.     CfgFile = CurrentCfgFile;
  634.  
  635.   // Use default file name if no file is specifed on command line
  636.   if(argc < 2) {
  637.     int FileStatus = CfgData->Load((char *)CfgFile);
  638.     if(!FileStatus) {
  639.       Error->Message("Cannot locate any database files!\n",
  640.              "Defaulting to: ", DefaultDBFileName);
  641.       FileName = (char *)DefaultDBFileName;
  642.       WelcomeMesgFile = (char *)DefaultWelcomeMesg;
  643.     }
  644.     else { 
  645. // *********************************************************** //
  646. // Add all startup config file entries here
  647. // *********************************************************** //
  648.       FileName = CfgData->GetStrValue("DBFileName");
  649.       AdminUser = CfgData->GetStrValue("AdminUser");
  650.       WelcomeMesgFile = CfgData->GetStrValue("WelcomeMessageFile");
  651. #ifdef __USE_MSW_PRINTING__
  652.   // Default values for wxWindows MSW Printing
  653.   mswp_lines_per_page = CfgData->GetIntValue("mswpLinesPerPage");
  654.   mswp_cell_length = CfgData->GetIntValue("mswpCellLength");
  655.   mswp_font_size = CfgData->GetIntValue("mswpFontSize");
  656.   mswp_left_margin = CfgData->GetIntValue("mswpLeftMargin");
  657.   mswp_orientation = CfgData->GetStrValue("mswpOrientation");
  658.   mswp_font = CfgData->GetStrValue("mswpFont");
  659.   mswp_doc_name = CfgData->GetStrValue("mswpDocumentName");
  660. #endif // __USE_MSW_PRINTING__
  661. // *********************************************************** //
  662.   
  663.       if(!FileName) {
  664.         UString comp("\nDefaulting to: ");
  665.     comp = comp + DefaultDBFileName;
  666.     Error->Message("DBFileName section missing in config file:\n",
  667.                CfgFile, comp.c_str());
  668.     FileName = (char *)DefaultDBFileName;
  669.       }
  670.     }
  671.   }
  672.   else {
  673.     FileName = argv[1];
  674.   }
  675.  
  676.   if(!AdminUser) {
  677.     AdminRights = 0;
  678.     frame->SetStatusText((char *)ProgramName);
  679.   }
  680.   else {
  681.     int result = strcmp(AdminUser, "TRUE");
  682.     if(result == 0) {
  683.       AdminRights = 1;
  684.       frame->SetStatusText("ADMIN USER");
  685.     }
  686.     else {
  687.       AdminRights = 0;
  688.       frame->SetStatusText((char *)ProgramName);
  689.     }
  690.   }
  691.  
  692.   if(!WelcomeMesgFile) 
  693.       WelcomeMesgFile = (char *)DefaultWelcomeMesg;
  694.   
  695. #ifdef __USE_MSW_PRINTING__
  696.   // Default values for wxWindows MSW Printing
  697.   if(mswp_lines_per_page > 0) {
  698.     MSWPrintSetup->lines_per_page = mswp_lines_per_page;
  699.     MSWPrintSetup->prev_lines_per_page = mswp_lines_per_page;
  700.     MSWPrintSetup->default_lines_per_page = mswp_lines_per_page;
  701.   }
  702.  
  703.   if(mswp_cell_length > 0) {
  704.     MSWPrintSetup->cell_length = mswp_cell_length;
  705.     MSWPrintSetup->prev_cell_length = mswp_cell_length;
  706.     MSWPrintSetup->default_cell_length = mswp_cell_length;
  707.   }
  708.  
  709.   if(mswp_font_size > 0) {
  710.     MSWPrintSetup->font_size = mswp_font_size;
  711.     MSWPrintSetup->prev_font_size = mswp_font_size;
  712.     MSWPrintSetup->default_font_size = mswp_font_size;
  713.   }
  714.  
  715.   if(mswp_left_margin > 0) {
  716.     MSWPrintSetup->lr_margin = mswp_left_margin;
  717.     MSWPrintSetup->prev_lr_margin = mswp_left_margin;
  718.     MSWPrintSetup->default_lr_margin = mswp_left_margin;
  719.   }
  720.  
  721.   if(mswp_orientation != 0) {
  722.     if(strcmp(mswp_orientation, "PORTRAIT") == 0) {
  723.       MSWPrintSetup->orientation = 1;
  724.       MSWPrintSetup->prev_orientation = 1;
  725.       MSWPrintSetup->default_orientation = 1;
  726.     }
  727.     if(strcmp(mswp_orientation, "LANDSCAPE") == 0) {
  728.       MSWPrintSetup->orientation = 0;
  729.       MSWPrintSetup->prev_orientation = 0;
  730.       MSWPrintSetup->default_orientation = 0;
  731.     }
  732.   }
  733.   
  734.   if(mswp_font != 0) {
  735.     if(strcmp(mswp_font, "SWISS") == 0) {
  736.       MSWPrintSetup->font = 0;
  737.       MSWPrintSetup->prev_font = 0;
  738.       MSWPrintSetup->default_font = 0;
  739.     }
  740.     if(strcmp(mswp_font, "ROMAN") == 0) {
  741.       MSWPrintSetup->font = 1;
  742.       MSWPrintSetup->prev_font = 1;
  743.       MSWPrintSetup->default_font = 1;
  744.     }
  745.     if(strcmp(mswp_font, "DECORATIVE") == 0) {
  746.       MSWPrintSetup->font = 2;
  747.       MSWPrintSetup->prev_font = 2;
  748.       MSWPrintSetup->default_font = 2;
  749.     }
  750.     if(strcmp(mswp_font, "MODERN") == 0) {
  751.       MSWPrintSetup->font = 3;
  752.       MSWPrintSetup->prev_font = 3;
  753.       MSWPrintSetup->default_font = 3;
  754.     }
  755.     if(strcmp(mswp_font, "SCRIPT") == 0) {
  756.       MSWPrintSetup->font = 4;
  757.       MSWPrintSetup->prev_font = 4;
  758.       MSWPrintSetup->default_font = 4;
  759.     }
  760.     if(strcmp(mswp_font, "SYSTEM") == 0) {
  761.       MSWPrintSetup->font = 5;
  762.       MSWPrintSetup->prev_font = 5;
  763.       MSWPrintSetup->default_font = 5;
  764.     }
  765.   }
  766.  
  767.   for(int i = 0; i < mswpDocNameLen; i++) mswpDocumentName[i] = 0;
  768.   if(mswp_doc_name != 0) 
  769.     strcpy(mswpDocumentName, mswp_doc_name);
  770.   else
  771.     strcpy(mswpDocumentName, ProgramName);
  772. #endif // __USE_MSW_PRINTING__
  773.  
  774.   CfgData->UnLoad(); // Unload the Config file from memory
  775.  
  776.   // Initialize global database pointer
  777.   // NOTE: Index file and data file will share the same file name
  778.   // with different file extensions. The data file will have a 
  779.   // .pod extension and the index file will have a .btx extension.
  780.   if(AdminRights == 1)
  781.     DB = new POD(FileName, RWMode, 1, CacheSize);
  782.   else
  783.     DB = new POD(FileName, ROMode, 1, CacheSize);
  784.   
  785.   astrdb = new StrDB(DB); // Initialize global buffer pointer
  786.   cstrdb = new StrDB(DB); // Initialize global buffer pointer
  787.   dstrdb = new StrDB(DB); // Initialize global buffer pointer
  788.   
  789.  
  790.   // Display the welcome message if it exists
  791.   frame->textWin->LoadFile(WelcomeMesgFile);
  792.   
  793.   // Return the main frame window
  794.   return frame;
  795. }
  796.  
  797. MyFrame::MyFrame(wxFrame *frame, char *title, int x, int y, int w, int h):
  798.   wxFrame(frame, title, x, y, w, h)
  799. {
  800.   textWin = 0;
  801.   apanel = 0;
  802.   cpanel = 0;
  803.   dpanel = 0;
  804.   addText = 0;
  805.   changeText = 0;
  806. }
  807.  
  808. Bool MyFrame::OnClose(void)
  809. // Define the behaviour for the frame closing
  810. {
  811.   // Close sub-frames
  812.   if(APanelFrame) {
  813.     APanelFrame->Close(TRUE);
  814.     delete APanelFrame;
  815.   }
  816.   
  817.   if(CPanelFrame) {
  818.     CPanelFrame->Close(TRUE);
  819.     delete CPanelFrame;
  820.   }
  821.   
  822.   if(DPanelFrame) {
  823.     DPanelFrame->Close(TRUE);
  824.     delete DPanelFrame;
  825.   }
  826.   
  827.   // Close main frame
  828.   Show(FALSE);
  829.  
  830.   // Clean up Variable Block Database objects
  831.   if(DB) delete DB;
  832.   if(astrdb) delete astrdb;
  833.   if(cstrdb) delete cstrdb;
  834.   if(dstrdb) delete dstrdb;
  835.   return TRUE;
  836. }
  837.  
  838. void MyFrame::OnMenuCommand(int id)
  839. // Intercept menu commands
  840. {
  841.   switch (id) {
  842.     case FILE_QUIT:
  843.       if (OnClose()) delete this;
  844.       break;
  845.  
  846.     case FILE_VBDSTATS:
  847.       textWin->Clear();
  848.       *(textWin) << "----- Database file statistics -----" << "\n";
  849.       VBDStats(textWin, DB->OpenDatabase());
  850.       *(textWin) << "----- Index file statistics -----" << "\n";
  851.       VBDStats(textWin, DB->OpenIndexFile());
  852.       break;
  853.  
  854.     case FILE_EXPORT:
  855.       ExportToASCII(*textWin);
  856.       break;
  857.  
  858.     case FILE_IMPORT:
  859.       ImportFromASCII(*textWin);
  860.       break;
  861.  
  862.     case FILE_BACKUP:
  863.       BackUp(*textWin);
  864.       break;
  865.  
  866.     case FILE_MERGE:
  867.       Merge(*textWin);
  868.       break;
  869.  
  870.     case FILE_TEMPLATE:
  871.       CreateTemplate(*textWin);
  872.       break;
  873.  
  874.     case FILE_COMPARE_INDEX:
  875.       CompareIndexFile(*textWin);
  876.       break;
  877.       
  878.     case FILE_REBUILD_INDEX:
  879.       RebuildIndexFile(*textWin);
  880.       break;
  881.  
  882.     case EDIT_CUT:
  883.       textWin->Cut();
  884.       break;
  885.  
  886.     case EDIT_COPY:
  887.       textWin->Copy();
  888.       break;
  889.       
  890.     case EDIT_PASTE:
  891.       textWin->Paste();
  892.       break;
  893.  
  894.     case DB_ADD: 
  895.       Add(*textWin);
  896.       break;
  897.       
  898.     case DB_CHANGE:
  899.       Change(*textWin);
  900.       break;
  901.       
  902.     case DB_REMOVE:
  903.       Remove(*textWin);
  904.       break;
  905.  
  906.     case DB_DISPLAY:
  907.       DisplayDB(*textWin);
  908.       break;
  909.  
  910.     case FIND_BYKEYNAME:
  911.       FindBy(*textWin, KeyName, KEYMEMBER);
  912.       break;
  913.       
  914.     case FIND_BYM2NAME:
  915.       FindBy(*textWin, M2Name, M2NAME);
  916.       break;
  917.  
  918.     case FIND_BYM3NAME:
  919.       FindBy(*textWin, M3Name, M3NAME);
  920.       break;
  921.  
  922.     case FIND_BYM4NAME:
  923.       FindBy(*textWin, M4Name, M4NAME);
  924.       break;
  925.  
  926.     case FIND_BYM5NAME:
  927.       FindBy(*textWin, M5Name, M5NAME);
  928.       break;
  929.  
  930.     case FIND_BYM6NAME:
  931.       FindBy(*textWin, M6Name, M6NAME);
  932.       break;
  933.  
  934.     case FIND_BYM7NAME:
  935.       FindBy(*textWin, M7Name, M7NAME);
  936.       break;
  937.  
  938.     case FIND_BYM8NAME:
  939.       FindBy(*textWin, M8Name, M8NAME);
  940.       break;
  941.  
  942.     case FIND_BYCOMMENTS:
  943.       FindBy(*textWin, Comments, COMMENTS);
  944.       break;
  945.  
  946. #ifdef __USE_MSW_PRINTING__
  947.     case WXPRINT_PRINT:
  948.       {
  949. #ifdef wx_msw
  950.       myApp.SetPrintMode(wxPRINT_WINDOWS);
  951. #else 
  952.       // Allow MSW style printing under UNIX
  953.       myApp.SetPrintMode(wxPRINT_POSTSCRIPT);
  954. #endif
  955.     wxPrintData printData;
  956.     if(MSWPrintSetup->orientation == 0) 
  957.       printData.SetOrientation(wxLANDSCAPE);
  958.     else
  959.       printData.SetOrientation(wxPORTRAIT);
  960.  
  961.     if(displaying_list) {
  962.       int yn = wxMessageBox("Print display list objects?",
  963.                 "Program Message", wxYES_NO|wxCENTRE);
  964.       if(yn == wxYES) print_list = 1; else print_list = 0;
  965.     }
  966.     else {
  967.       print_list = 0;
  968.     }
  969.  
  970.     wxPrinter printer(&printData);
  971.     wStrDBPrint printout((char *)ProgramName);
  972.     if (!printer.Print(this, &printout, TRUE))
  973.       wxMessageBox("The document was not printed.",
  974.                "Printing", wxOK);
  975.     break;
  976.       }
  977.  
  978.     case WXPRINT_PREVIEW:
  979.       {
  980. #ifdef wx_msw
  981.       myApp.SetPrintMode(wxPRINT_WINDOWS);
  982. #else 
  983.       // Allow MSW style printing under UNIX
  984.       myApp.SetPrintMode(wxPRINT_POSTSCRIPT);
  985. #endif
  986.     wxPrintData printData;
  987.     if(MSWPrintSetup->orientation == 0) 
  988.       printData.SetOrientation(wxLANDSCAPE);
  989.     else
  990.       printData.SetOrientation(wxPORTRAIT);
  991.  
  992.     if(displaying_list) {
  993.       int yn = wxMessageBox("Print display list objects?",
  994.                 "Program Message", wxYES_NO|wxCENTRE);
  995.       if(yn == wxYES) print_list = 1; else print_list = 0;
  996.     }
  997.     else {
  998.       print_list = 0;
  999.     }
  1000.     
  1001.     // Pass two printout objects: for preview, and possible printing.
  1002.     wxPrintPreview *preview = \
  1003.       new wxPrintPreview(new wStrDBPrint((char *)ProgramName),
  1004.                  new wStrDBPrint((char *)ProgramName),
  1005.                  &printData);
  1006.  
  1007.     if (!preview->Ok()) {
  1008.       delete preview;
  1009.       wxMessageBox("There was a problem previewing.", 
  1010.                "Previewing", wxOK);
  1011.       return;
  1012.     }
  1013.  
  1014.     wxPreviewFrame *frame = new wxPreviewFrame(preview,
  1015.                            this,
  1016.                            (char *)ProgramName,
  1017.                            100, 100, 600, 650);
  1018.     frame->Centre(wxBOTH);
  1019.     frame->Initialize();
  1020.     frame->Show(TRUE);
  1021.     break;
  1022.       }
  1023.     
  1024.     case WXPRINT_PRINTER_SETUP:
  1025.       {
  1026. #ifdef wx_msw
  1027.       myApp.SetPrintMode(wxPRINT_WINDOWS);
  1028. #else 
  1029.       // Allow MSW style printing under UNIX
  1030.       myApp.SetPrintMode(wxPRINT_POSTSCRIPT);
  1031. #endif
  1032.     wxPrintData printData;
  1033.  
  1034.     if(MSWPrintSetup->orientation == 0) 
  1035.       printData.SetOrientation(wxLANDSCAPE);
  1036.     else
  1037.       printData.SetOrientation(wxPORTRAIT);
  1038.       
  1039.     wxPrintDialog printerDialog(this, &printData);
  1040.     printerDialog.GetPrintData().SetSetupDialog(TRUE);
  1041.     printerDialog.Show(TRUE);
  1042.     break;
  1043.       }
  1044.  
  1045.     case WXPRINT_PAGE_SETUP:
  1046.       {
  1047.     int xpos=300; int ypos=300; int width=300; 
  1048. #ifdef wx_msw
  1049.     int height=250;
  1050. #else 
  1051.       // Allow MSW style printing under UNIX
  1052.     int height=350;
  1053. #endif
  1054.  
  1055.       wxPageDialog = new wxDialogBox(this, "Page Setup", TRUE,
  1056.                        xpos, ypos, width, height,
  1057.                        wxDEFAULT_DIALOG_STYLE,
  1058.                        "Page Setup");
  1059.     
  1060.     wxPageDialog->Centre();
  1061.     wxPageDialog->NewLine();
  1062.     LppSlider = new wxSlider(wxPageDialog, NULL, "Lines Per Page",
  1063.                  MSWPrintSetup->lines_per_page,
  1064.                  1, 200, 200);
  1065.     wxPageDialog->NewLine();
  1066.     CellSlider = new wxSlider(wxPageDialog, NULL, "Cell Length",
  1067.                   MSWPrintSetup->cell_length,
  1068.                   1, 50, 150);
  1069.     wxPageDialog->NewLine();
  1070.     FsSlider = new wxSlider(wxPageDialog, NULL, "Font Size   ",
  1071.                 MSWPrintSetup->font_size,
  1072.                 1, 50, 150);
  1073.     wxPageDialog->NewLine();
  1074.     LRMSlider = new wxSlider(wxPageDialog, NULL, "Left Margin",
  1075.                 MSWPrintSetup->lr_margin,
  1076.                 1, 20, 150);
  1077.     wxPageDialog->NewLine();
  1078.     wxMessage *om = new wxMessage(wxPageDialog,
  1079.           "The Orientation must match the Printer Setup"); 
  1080.     wxPageDialog->NewLine();
  1081.  
  1082.     OrientationChoice = new wxChoice(wxPageDialog, NULL, "Orientation",
  1083.                      -1, -1, -1, -1, 2, OrChoiceStrings);
  1084.  
  1085.     OrientationChoice->SetSelection(MSWPrintSetup->orientation);
  1086.     wxPageDialog->NewLine();
  1087.     
  1088.     FontChoice = new wxChoice(wxPageDialog, NULL, "Font",
  1089.                   -1, -1, -1, -1, 6, FontChoiceStrings);
  1090.     FontChoice->SetSelection(MSWPrintSetup->font);
  1091.     wxPageDialog->NewLine();
  1092.     
  1093.         btn_pdb_close = new wxButton(wxPageDialog, (wxFunction)&page_btn_proc,
  1094.                      "Close", 10, -1, -1, -1);
  1095.         btn_pdb_close->SetClientData((char*)PAGE_DIALOG_BUTTON_CLOSE);
  1096.  
  1097.     btn_pdb_accept = new wxButton(wxPageDialog, (wxFunction)&page_btn_proc,
  1098.                      "Accept", 60, -1, -1, -1);
  1099.     btn_pdb_accept->SetClientData((char*)PAGE_DIALOG_BUTTON_ACCEPT);
  1100.     
  1101.     btn_pdb_cancel = new wxButton(wxPageDialog, (wxFunction)&page_btn_proc,
  1102.                      "Cancel", 118, -1, -1, -1);
  1103.     btn_pdb_cancel->SetClientData((char*)PAGE_DIALOG_BUTTON_CANCEL);
  1104.     
  1105.     btn_pdb_default = new wxButton(wxPageDialog,
  1106.                        (wxFunction)&page_btn_proc,
  1107.                        "Default", 175, -1, -1, -1);
  1108.     btn_pdb_default->SetClientData((char*)PAGE_DIALOG_BUTTON_DEFAULT);
  1109.  
  1110.     wxPageDialog->Show(TRUE);
  1111.     break;
  1112.       }
  1113. #endif //  __USE_MSW_PRINTING__
  1114.     
  1115.     case PRINT_POSTSCRIPT:
  1116.       PostScriptPrint(*textWin);
  1117.       break;
  1118.  
  1119.     case PRINT_HTML:
  1120.       HTMLPrint(*textWin);
  1121.       break;
  1122.  
  1123.     case PRINT_ASCIIALL:
  1124.       ASCIIPrintAll(*textWin);
  1125.       break;
  1126.  
  1127.     case PRINT_ASCIILONG:
  1128.       ASCIIPrintAllLong(*textWin);
  1129.       break;
  1130.  
  1131.     case PRINT_ASCIIOBJECT:
  1132.       ASCIIPrintObject(*textWin);  
  1133.       break;
  1134.  
  1135.     case VIEW_CLEAR:
  1136.       Clear(*textWin);
  1137.       break;
  1138.  
  1139.     case HELP_ABOUT: {
  1140.       char *s = VerNumber();
  1141.       UString mesg(ProgramName);
  1142.       mesg = mesg + "\nVersion Number " + s;
  1143.       wxMessageBox(mesg.c_str(), "About", wxOK|wxCENTRE);
  1144.       break;
  1145.     }
  1146.     
  1147.     case HELP_USERLEVEL: {
  1148.       UString mesg;
  1149.       if(AdminRights) {
  1150.     mesg = mesg + "You have Admin User Privileges\n" + \
  1151.       "As defined in the " + DefaultCfgFile + " config file\n";
  1152.     wxMessageBox(mesg.c_str(), "Access Level", wxOK|wxCENTRE);
  1153.       }
  1154.       else {
  1155.     mesg = mesg + "You do not have Admin User Privileges\n" + \
  1156.       "As defined in the " + DefaultCfgFile + " config file\n";
  1157.     wxMessageBox(mesg.c_str(), "Access Level", wxOK|wxCENTRE);
  1158.       }
  1159.       break;
  1160.     }
  1161.   }
  1162. }
  1163.  
  1164. void MyTextWindow::OnChar(wxKeyEvent& event)
  1165. {
  1166.   if(event.keyCode == CONTROL('x')) {
  1167.     Cut(); 
  1168.     frame->SetStatusText("Cut text and copied to clipboard");
  1169.   }
  1170.  
  1171.   if(event.keyCode == CONTROL('c')) {
  1172.     Copy(); 
  1173.     frame->SetStatusText("Copied text from clipboard");
  1174.   }
  1175.  
  1176.   if(event.keyCode == CONTROL('v')) {
  1177.     Paste(); 
  1178.     frame->SetStatusText("Pasted text from clipboard");
  1179.   }
  1180.  
  1181.   wxTextWindow::OnChar(event);  // Process the default behavior
  1182. }
  1183.  
  1184. void MyFrame::OnSize(int w, int h)
  1185. {
  1186.   wxFrame::OnSize(w, h);
  1187. }
  1188.  
  1189. MyText::MyText(wxPanel *parent, wxFunction func, char *label,
  1190.              char *value, int x, int y, int width, int height ,
  1191.              long style, char *name) :
  1192.   wxText(parent, func, label, value,x, y, width, height , style, name)
  1193. {
  1194.   key = m2 = m3 = m4 = m5 = m6 = m7 = m8 = cmt = 0;
  1195. }
  1196.  
  1197. MyText::~MyText()
  1198. {
  1199.   if(key) delete key;
  1200.   if(m2) delete m2;
  1201.   if(m3) delete m3;
  1202.   if(m4) delete m4;
  1203.   if(m5) delete m5;
  1204.   if(m6) delete m6;
  1205.   if(m7) delete m7;
  1206.   if(m8) delete m8;
  1207.   if(cmt) delete cmt;
  1208. }
  1209.  
  1210. void Clear(MyTextWindow& textWin)
  1211. {
  1212.   textWin.Clear();
  1213. }
  1214.  
  1215. char *VerNumber()
  1216. // Version number for this windows program. Edit the version.h
  1217. // file to change this program's version number
  1218. {
  1219.  char buf[10];
  1220.  sprintf(buf, "%.3f", VersionNumber); 
  1221.  int len = strlen(buf);
  1222.  char *s = new char[len+1];
  1223.  s[len+1] = '\0';
  1224.  strcpy(s, buf);
  1225.  return s;
  1226. }
  1227.  
  1228. void text_proc(wxText &but, wxCommandEvent &event)
  1229. {
  1230.   // Nothing to do
  1231. }
  1232.  
  1233. void AddBtnProc(wxButton& but, wxCommandEvent& event)
  1234. {
  1235.   UString sbuf; // Character string input buffer
  1236.   long tag = (long)but.GetClientData() ;
  1237.  
  1238.   if(tag == ADD_BUTTON_ADD) {
  1239.     UString key_name;
  1240.     UString m2_name;
  1241.     UString m3_name;
  1242.     UString m4_name;
  1243.     UString m5_name;
  1244.     UString m6_name;
  1245.     UString m7_name;
  1246.     UString m8_name;
  1247.     UString cmts;
  1248.  
  1249.     if(KeyName != 0) key_name = frame->addText->key->GetValue();
  1250.     if(M2Name != 0) m2_name = frame->addText->m2->GetValue();
  1251.     if(M3Name != 0) m3_name = frame->addText->m3->GetValue();
  1252.     if(M4Name != 0) m4_name = frame->addText->m4->GetValue();
  1253.     if(M5Name != 0) m5_name = frame->addText->m5->GetValue();
  1254.     if(M6Name != 0) m6_name = frame->addText->m6->GetValue();
  1255.     if(M7Name != 0) m7_name = frame->addText->m7->GetValue();
  1256.     if(M8Name != 0) m8_name = frame->addText->m8->GetValue();
  1257.     if(Comments != 0) cmts = frame->addText->cmt->GetValue();
  1258.  
  1259.     // Remove any leading space from the key name entry
  1260.     int offset = key_name.Find(" ");
  1261.     if(offset == 0) key_name.DeleteAt(offset, 1);
  1262.     
  1263.     if(key_name == "") { // Check for a key name valid input
  1264.       sbuf = sbuf + "Invalid " + KeyName + " input!";
  1265.       frame->textWin->WriteText(sbuf.c_str());
  1266.       frame->textWin->WriteText("\n");
  1267.       Error->Message(sbuf.c_str());
  1268.       return;
  1269.     }
  1270.  
  1271.     StrDB strdb(DB);
  1272.     strdb.SetKM(key_name);
  1273.     FAU addr = strdb.FindObject();
  1274.     
  1275.     if(addr) {
  1276.       sbuf = sbuf + "An Entry for " + key_name +  " already exists!";
  1277.       frame->textWin->WriteText(sbuf.c_str());
  1278.       frame->textWin->WriteText("\n");
  1279.       Error->Message(sbuf.c_str());
  1280.       return;
  1281.     }
  1282.  
  1283.     if(KeyName != 0) astrdb->SetKM(key_name.c_str());
  1284.     if(M2Name != 0) astrdb->SetM2(m2_name.c_str());
  1285.     if(M3Name != 0) astrdb->SetM3(m3_name.c_str());
  1286.     if(M4Name != 0) astrdb->SetM4(m4_name.c_str());
  1287.     if(M5Name != 0) astrdb->SetM5(m5_name.c_str());
  1288.     if(M6Name != 0) astrdb->SetM6(m6_name.c_str());
  1289.     if(M7Name != 0) astrdb->SetM7(m7_name.c_str());
  1290.     if(M8Name != 0) astrdb->SetM8(m8_name.c_str());
  1291.     if(Comments != 0) astrdb->SetCM(cmts.c_str());
  1292.     
  1293.     addr = astrdb->AddObject(0); // Write the object to the file
  1294.  
  1295.     if(!addr) {
  1296.       sbuf = sbuf + "Could not add Entry for " + astrdb->GetKM();
  1297.       frame->textWin->WriteText(sbuf.c_str());
  1298.       frame->textWin->WriteText("\n");
  1299.       Error->Message(sbuf.c_str());
  1300.       return;
  1301.     }
  1302.  
  1303.     sbuf = sbuf + "Added Entry for " + astrdb->GetKM();
  1304.     frame->textWin->WriteText(sbuf.c_str());
  1305.     frame->textWin->WriteText("\n");
  1306.     ClearAddPanel();
  1307.  
  1308.     if(displaying_list) {
  1309.       InMemCopy inmemcopy(astrdb->GetKM(), astrdb->ObjectAddress(),
  1310.               astrdb->GetClassID());
  1311.       dllist->StoreNode(inmemcopy);
  1312.     }
  1313.   }
  1314.   
  1315.   if(tag == ADD_BUTTON_CANCEL) {
  1316.     ClearAddPanel();
  1317.     return;
  1318.   }
  1319.  
  1320.   if(tag == ADD_BUTTON_CLOSE) {
  1321.     APanelFrame->Show(FALSE);
  1322.     return;
  1323.   }
  1324.  
  1325.   if(tag == ADD_BUTTON_REVERT) {
  1326.     if(KeyName != 0) 
  1327.       if(astrdb->GetKM())
  1328.     frame->addText->key->SetValue(astrdb->GetKM());
  1329.     if(M2Name != 0)  
  1330.       if(astrdb->GetM2())
  1331.     frame->addText->m2->SetValue(astrdb->GetM2());
  1332.     if(M3Name != 0) 
  1333.       if(astrdb->GetM3())
  1334.     frame->addText->m3->SetValue(astrdb->GetM3());
  1335.     if(M4Name != 0)  
  1336.       if(astrdb->GetM4())
  1337.     frame->addText->m4->SetValue(astrdb->GetM4());
  1338.     if(M5Name != 0)  
  1339.       if(astrdb->GetM5())
  1340.     frame->addText->m5->SetValue(astrdb->GetM5());
  1341.     if(M6Name != 0)  
  1342.       if(astrdb->GetM6())
  1343.     frame->addText->m6->SetValue(astrdb->GetM6());
  1344.     if(M7Name != 0)  
  1345.       if(astrdb->GetM7())
  1346.     frame->addText->m7->SetValue(astrdb->GetM7());
  1347.     if(M8Name != 0)  
  1348.       if(astrdb->GetM8())
  1349.     frame->addText->m8->SetValue(astrdb->GetM8());
  1350.     if(Comments != 0)  
  1351.       if(astrdb->GetCM())
  1352.     frame->addText->cmt->SetValue(astrdb->GetCM());
  1353.     return;
  1354.   }
  1355. }
  1356.  
  1357. void ClearAddPanel()
  1358. {
  1359.   if(KeyName != 0) frame->addText->key->SetValue("");
  1360.   if(M2Name != 0) frame->addText->m2->SetValue("");
  1361.   if(M3Name != 0) frame->addText->m3->SetValue("");
  1362.   if(M4Name != 0) frame->addText->m4->SetValue("");
  1363.   if(M5Name != 0) frame->addText->m5->SetValue("");
  1364.   if(M6Name != 0) frame->addText->m6->SetValue("");
  1365.   if(M7Name != 0) frame->addText->m7->SetValue("");
  1366.   if(M8Name != 0) frame->addText->m8->SetValue("");
  1367.   if(Comments != 0) frame->addText->cmt->SetValue("");
  1368. }
  1369.  
  1370. void Add(MyTextWindow &textWin)
  1371. {
  1372.   if(!AdminRights) {
  1373.       wxMessageBox("You do not have Admin User Privileges\n",
  1374.            "Program Message", wxOK|wxCENTRE);
  1375.     return;
  1376.   }
  1377.     
  1378.   textWin.Clear();
  1379.   textWin << "Adding objects to database..." << "\n";
  1380.   textWin << "\n";
  1381.   
  1382.   if(KeyName == 0) { // Alert user that key name is not set 
  1383.     textWin << "Primary Key Name value is not set in db config file!"
  1384.         << "\n" << "Cannot add any objects." << "\n";
  1385.     
  1386.     return;
  1387.   }
  1388.   
  1389.   APanelFrame->Show(TRUE); // Show the Add Panel Frame
  1390. }
  1391.  
  1392. void ChBtnProc(wxButton& but, wxCommandEvent& event)
  1393. {
  1394.   UString sbuf, key_name; // Character input string buffers
  1395.   long tag = (long)but.GetClientData() ;
  1396.   int offset;
  1397.   
  1398.   if(tag == CHANGE_BUTTON_SH) {  
  1399.     if(KeyName != 0) key_name = frame->changeText->key->GetValue();
  1400.  
  1401.     // Remove any leading space from the key name entry
  1402.     offset = key_name.Find(" ");
  1403.     if(offset == 0) key_name.DeleteAt(offset, 1);
  1404.     
  1405.     if(key_name == "") { // Check for a key name valid input
  1406.       sbuf = sbuf + "Invalid " + KeyName + " input!";
  1407.       frame->textWin->WriteText(sbuf.c_str());
  1408.       frame->textWin->WriteText("\n");
  1409.       Error->Message(sbuf.c_str());
  1410.       btn_ch_cm->Enable(0);
  1411.       return;
  1412.     }
  1413.     
  1414.     StrDB strdb(DB);
  1415.     strdb.SetKM(key_name);
  1416.  
  1417.     if(!(__LWORD__)strdb.FindObject()) {
  1418.       sbuf = sbuf + "Could not find an entry for " + key_name;
  1419.       frame->textWin->WriteText(sbuf.c_str());
  1420.       frame->textWin->WriteText("\n");
  1421.       Error->Message(sbuf.c_str());
  1422.       btn_ch_cm->Enable(0);
  1423.       return;
  1424.     }
  1425.  
  1426.     cstrdb->Copy(strdb);
  1427.     
  1428.     if(M2Name != 0)  
  1429.       if(cstrdb->GetM2())
  1430.     frame->changeText->m2->SetValue(cstrdb->GetM2());
  1431.     if(M3Name != 0) 
  1432.       if(cstrdb->GetM3())
  1433.     frame->changeText->m3->SetValue(cstrdb->GetM3());
  1434.     if(M4Name != 0)  
  1435.       if(cstrdb->GetM4())
  1436.     frame->changeText->m4->SetValue(cstrdb->GetM4());
  1437.     if(M5Name != 0)  
  1438.       if(cstrdb->GetM5())
  1439.     frame->changeText->m5->SetValue(cstrdb->GetM5());
  1440.     if(M6Name != 0)  
  1441.       if(cstrdb->GetM6())
  1442.     frame->changeText->m6->SetValue(cstrdb->GetM6());
  1443.     if(M7Name != 0)  
  1444.       if(cstrdb->GetM7())
  1445.     frame->changeText->m7->SetValue(cstrdb->GetM7());
  1446.     if(M8Name != 0)  
  1447.       if(cstrdb->GetM8())
  1448.     frame->changeText->m8->SetValue(cstrdb->GetM8());
  1449.     if(Comments != 0)  
  1450.       if(cstrdb->GetCM())
  1451.     frame->changeText->cmt->SetValue(cstrdb->GetCM());
  1452.     btn_ch_cm->Enable(1); // Enable the commit button
  1453.   }
  1454.  
  1455.   if(tag == CHANGE_BUTTON_CM) {
  1456.     if(KeyName != 0) key_name = frame->changeText->key->GetValue();
  1457.  
  1458.     // Remove any leading space from the key name entry
  1459.     offset = key_name.Find(" ");
  1460.     if(offset == 0) key_name.DeleteAt(offset, 1);
  1461.     
  1462.     if(key_name == "") { // Check for a key name valid input
  1463.       sbuf = sbuf + "Invalid " + KeyName + " input!";
  1464.       frame->textWin->WriteText(sbuf.c_str());
  1465.       frame->textWin->WriteText("\n");
  1466.       Error->Message(sbuf.c_str());
  1467.       btn_ch_cm->Enable(0);
  1468.       return;
  1469.     }
  1470.  
  1471.     StrDB changed(DB); // Buffer used to store changes
  1472.     if(KeyName != 0) changed.SetKM(frame->changeText->key->GetValue());
  1473.     if(M2Name != 0) changed.SetM2(frame->changeText->m2->GetValue());
  1474.     if(M3Name != 0) changed.SetM3(frame->changeText->m3->GetValue());
  1475.     if(M4Name != 0) changed.SetM4(frame->changeText->m4->GetValue());
  1476.     if(M5Name != 0) changed.SetM5(frame->changeText->m5->GetValue());
  1477.     if(M6Name != 0) changed.SetM6(frame->changeText->m6->GetValue());
  1478.     if(M7Name != 0) changed.SetM7(frame->changeText->m7->GetValue());
  1479.     if(M8Name != 0) changed.SetM8(frame->changeText->m8->GetValue());
  1480.     if(Comments != 0) changed.SetCM(frame->changeText->cmt->GetValue());
  1481.  
  1482.     // Disable the commit button after changing the object
  1483.     btn_ch_cm->Enable(0);
  1484.  
  1485.     if(changed.FullCompare(*cstrdb)) { // The object has not changed
  1486.       sbuf = sbuf + "No changes to commit for " + cstrdb->GetKM();
  1487.       frame->textWin->WriteText(sbuf.c_str());
  1488.       frame->textWin->WriteText("\n");
  1489.       Error->Message(sbuf.c_str());
  1490.       ClearChangePanel();
  1491.  
  1492.       if(displaying_list) { //Objects are being displayed
  1493.     if(!dllist->IsEmpty()) DPanelFrame->Show(TRUE);
  1494.       }
  1495.       btn_ch_cm->Enable(0);
  1496.       return;
  1497.     }
  1498.  
  1499.     UString key_name(changed.GetKM());
  1500.     UString old_key_name(cstrdb->GetKM());
  1501.  
  1502.     // If the key name is changed, ensure no duplicates are added
  1503.     if(key_name != old_key_name) {
  1504.       if((__LWORD__)changed.FindObject()) {
  1505.     sbuf = sbuf + "An Entry for " + key_name + " already exists!";
  1506.     frame->textWin->WriteText(sbuf.c_str());
  1507.     frame->textWin->WriteText("\n");
  1508.     Error->Message(sbuf.c_str());
  1509.     if(displaying_list) { // Objects are being displayed
  1510.       if(!dllist->IsEmpty()) DPanelFrame->Show(TRUE);
  1511.     }
  1512.     btn_ch_cm->Enable(0);
  1513.     return;
  1514.       }
  1515.     }
  1516.  
  1517.     FAU oa = cstrdb->ObjectAddress(); // Record address before deleting
  1518.     cstrdb->DeleteObject(); // Remove the object  
  1519.     changed.AddObject(0); // Add the changed object back to the database
  1520.  
  1521.     sbuf = sbuf + "Commited changes for " + changed.GetKM();
  1522.     frame->textWin->WriteText(sbuf.c_str());
  1523.     frame->textWin->WriteText("\n");
  1524.     ClearChangePanel();
  1525.     
  1526.     // Update any list entries for display panel
  1527.     if(displaying_list) { // Objects are being displayed
  1528.       if(dllist->IsEmpty()) {
  1529.     displaying_list = 0;
  1530.     DPanelFrame->Show(FALSE);
  1531.     return;
  1532.       }
  1533.       InMemCopy inmemcopy(cstrdb->GetKM(), oa, cstrdb->GetClassID());
  1534.       DNode<InMemCopy> *prevptr = dllistptr;
  1535.       dllistptr = (DNode<InMemCopy> *)dllist->Find(inmemcopy);
  1536.       if(dllistptr) {
  1537.     dllistptr->Data.key = changed.GetKM();    
  1538.     dllistptr->Data.object_address = changed.ObjectAddress();
  1539.     dllistptr->Data.class_id = changed.GetClassID();
  1540.     if(displaying_list) {
  1541.       DPanelFrame->Show(TRUE);
  1542.       DisplayObject(changed);
  1543.     }
  1544.       }
  1545.       else {
  1546.        dllistptr = prevptr;
  1547.        dllistptr->Data.key = changed.GetKM();    
  1548.        dllistptr->Data.object_address = changed.ObjectAddress();
  1549.        dllistptr->Data.class_id = changed.GetClassID();
  1550.        if(displaying_list) {
  1551.      DPanelFrame->Show(TRUE);
  1552.      DisplayObject(changed);
  1553.        }
  1554.       }
  1555.     }
  1556.   }
  1557.   
  1558.   if(tag == CHANGE_BUTTON_CANCEL) {
  1559.     ClearChangePanel();
  1560.     if(displaying_list) { // Objects are being displayed
  1561.       if(!dllist->IsEmpty()) DPanelFrame->Show(TRUE);
  1562.     }
  1563.     btn_ch_cm->Enable(0);
  1564.     return;
  1565.   }
  1566.  
  1567.   if(tag == CHANGE_BUTTON_CLOSE) {
  1568.     ClearChangePanel();
  1569.     CPanelFrame->Show(FALSE);
  1570.     btn_ch_cm->Enable(0);
  1571.     return;
  1572.   }
  1573.  
  1574.   if(tag == CHANGE_BUTTON_REVERT) {
  1575.     if(KeyName != 0)  
  1576.       if(cstrdb->GetKM())
  1577.     frame->changeText->key->SetValue(cstrdb->GetKM());
  1578.     if(M2Name != 0)  
  1579.       if(cstrdb->GetM2())
  1580.     frame->changeText->m2->SetValue(cstrdb->GetM2());
  1581.     if(M3Name != 0) 
  1582.       if(cstrdb->GetM3())
  1583.     frame->changeText->m3->SetValue(cstrdb->GetM3());
  1584.     if(M4Name != 0)  
  1585.       if(cstrdb->GetM4())
  1586.     frame->changeText->m4->SetValue(cstrdb->GetM4());
  1587.     if(M5Name != 0)  
  1588.       if(cstrdb->GetM5())
  1589.     frame->changeText->m5->SetValue(cstrdb->GetM5());
  1590.     if(M6Name != 0)  
  1591.       if(cstrdb->GetM6())
  1592.     frame->changeText->m6->SetValue(cstrdb->GetM6());
  1593.     if(M7Name != 0)  
  1594.       if(cstrdb->GetM7())
  1595.     frame->changeText->m7->SetValue(cstrdb->GetM7());
  1596.     if(M8Name != 0)  
  1597.       if(cstrdb->GetM8())
  1598.     frame->changeText->m8->SetValue(cstrdb->GetM8());
  1599.     if(Comments != 0)  
  1600.       if(cstrdb->GetCM())
  1601.     frame->changeText->cmt->SetValue(cstrdb->GetCM());
  1602.     btn_ch_cm->Enable(0);
  1603.     return;
  1604.   }
  1605. }
  1606.  
  1607. void ClearChangePanel()
  1608. {
  1609.   if(KeyName != 0) frame->changeText->key->SetValue("");
  1610.   if(M2Name != 0) frame->changeText->m2->SetValue("");
  1611.   if(M3Name != 0) frame->changeText->m3->SetValue("");
  1612.   if(M4Name != 0) frame->changeText->m4->SetValue("");
  1613.   if(M5Name != 0) frame->changeText->m5->SetValue("");
  1614.   if(M6Name != 0) frame->changeText->m6->SetValue("");
  1615.   if(M7Name != 0) frame->changeText->m7->SetValue("");
  1616.   if(M8Name != 0) frame->changeText->m8->SetValue("");
  1617.   if(Comments != 0) frame->changeText->cmt->SetValue("");
  1618. }
  1619.  
  1620. void Change(MyTextWindow &textWin)
  1621. {
  1622.   if(!AdminRights) {
  1623.       wxMessageBox("You do not have Admin User Privileges\n",
  1624.            "Program Message", wxOK|wxCENTRE);
  1625.     return;
  1626.   }
  1627.  
  1628.   textWin.Clear();
  1629.   textWin << "Changing objects in database..." << "\n";
  1630.   textWin << "\n";
  1631.   
  1632.   if(KeyName == 0) { // Alert user that key name is not set 
  1633.     textWin << "Primary Key Name value is not set in db config file!"
  1634.         << "\n" << "Cannot change any objects." << "\n";
  1635.     
  1636.     return;
  1637.   }
  1638.   
  1639.   CPanelFrame->Show(TRUE); // Show the Add Panel Frame
  1640. }
  1641.  
  1642. void Remove(MyTextWindow &textWin, char *keyNM)
  1643. {
  1644.   if(KeyName == 0) return;
  1645.  
  1646.   if(!AdminRights) {
  1647.     wxMessageBox("You do not have Admin User Privileges\n",
  1648.          "Program Message", wxOK|wxCENTRE);
  1649.     return;
  1650.   }
  1651.  
  1652.   textWin.Clear();
  1653.   textWin << "Removing object from database..." << "\n";
  1654.  
  1655.   UString key_name;
  1656.   UString comp;
  1657.   char *buf;
  1658.   
  1659.   if(!keyNM) {
  1660.     comp = comp + "Enter " + KeyName + " to Remove:";
  1661.     buf = wxGetTextFromUser(comp.c_str(), "String Input");
  1662.  
  1663.     if(!buf) {
  1664.       textWin << "Canceled." << "\n";
  1665.       return;
  1666.     }
  1667.  
  1668.     key_name = buf;
  1669.     
  1670.     // Remove any leading space from the key name entry
  1671.     int offset = key_name.Find(" ");
  1672.     if(offset == 0) key_name.DeleteAt(offset, 1);
  1673.   
  1674.     if(key_name == "") { // Check for a key name valid input
  1675.       comp.DeleteAt(0, comp.length());
  1676.       comp = comp + "Invalid " + KeyName + " input!";
  1677.       frame->textWin->WriteText(comp.c_str());
  1678.       frame->textWin->WriteText("\n");
  1679.       Error->Message(comp.c_str());
  1680.       return;
  1681.     }
  1682.   }  
  1683.   else
  1684.     key_name = keyNM; // Key name memeber
  1685.  
  1686.   StrDB strdb(DB);
  1687.   strdb.SetKM(key_name);
  1688.  
  1689.   FAU addr = strdb.FindObject();
  1690.   
  1691.   if(!addr) { 
  1692.     comp.DeleteAt(0, comp.length());
  1693.     comp = comp + "Could not find an entry for: " + key_name.c_str();
  1694.     Error->Message(comp.c_str());
  1695.     textWin << comp.c_str() << "\n";
  1696.     return;
  1697.   }
  1698.  
  1699.   int yn = wxMessageBox("Are you sure you want to remove",
  1700.                "Program Message", wxYES_NO|wxCENTRE);
  1701.  
  1702.   if(yn == wxNO) return;
  1703.   
  1704.  
  1705.   InMemCopy listdata(strdb.GetKM(), strdb.ObjectAddress(),
  1706.              strdb.GetClassID());
  1707.  
  1708.   strdb.DeleteObject();
  1709.  
  1710.   textWin << "Removed entry for: " << key_name.c_str() << "\n";
  1711.  
  1712.   // Update display object panel list 
  1713.   if(displaying_list) {
  1714.     if(dllist->IsEmpty()) {
  1715.       displaying_list = 0;
  1716.       DPanelFrame->Show(TRUE);
  1717.       return;
  1718.     }
  1719.     DNode<InMemCopy> *dllptr = 0;
  1720.     dllptr = (DNode<InMemCopy> *)dllist->Find(listdata);
  1721.     if(dllptr) {
  1722.       dllist->Delete(dllptr);
  1723.       wxCommandEvent wxevent1(wxEVENT_TYPE_BUTTON_COMMAND);
  1724.       DsBtnProc(*btn_ds_nx, wxevent1); // Simulate pushing the Next Button
  1725.     }
  1726.   }
  1727. }
  1728.  
  1729. void DsBtnProc(wxButton& but, wxCommandEvent& event)
  1730. {
  1731.   char *sbuf = 0; // Character string buffer
  1732.   long tag = (long)but.GetClientData() ;
  1733.   StrDB strdb(DB);
  1734.   
  1735.   if(tag == DISPLAY_BUTTON_NX) {
  1736.     if(!dllistptr) return;
  1737.     if(!dllist) return;
  1738.     if(dllist->IsEmpty()) {
  1739.       ClearDisplayPanel();
  1740.       wxMessageBox("The display list is empty\n",
  1741.            "Program Message", wxOK|wxCENTRE);
  1742.       return;
  1743.     }
  1744.     else
  1745.       dllistptr = dllistptr->GetNext();
  1746.  
  1747.     if(!dllist->IsHeader(dllistptr)) {
  1748.       strdb.ReadObject(dllistptr->Data.object_address);
  1749.       DisplayObject(strdb);
  1750.     }
  1751.     else {
  1752.       wxMessageBox("Reached the end of the list\n",
  1753.            "Program Message", wxOK|wxCENTRE);
  1754.       dllistptr = dllist->GetFront();
  1755.       strdb.ReadObject(dllistptr->Data.object_address);
  1756.       DisplayObject(strdb);
  1757.     }
  1758.   }
  1759.  
  1760.   if(tag == DISPLAY_BUTTON_PREV) {
  1761.     if(!dllistptr) return;
  1762.     if(!dllist) return;
  1763.     if(dllist->IsEmpty()) {
  1764.       ClearDisplayPanel();
  1765.       wxMessageBox("The display list is empty\n",
  1766.            "Program Message", wxOK|wxCENTRE);
  1767.       return;
  1768.     }
  1769.     else
  1770.       dllistptr = dllistptr->GetPrior();
  1771.  
  1772.     if(!dllist->IsHeader(dllistptr)) {
  1773.       strdb.ReadObject(dllistptr->Data.object_address);
  1774.       DisplayObject(strdb);
  1775.     }
  1776.     else {
  1777.       wxMessageBox("Reached the beginning of the list\n",
  1778.            "Program Message", wxOK|wxCENTRE);
  1779.       dllistptr = dllist->GetBack();
  1780.       strdb.ReadObject(dllistptr->Data.object_address);
  1781.       DisplayObject(strdb);
  1782.     }
  1783.   }
  1784.  
  1785.   if(tag == DISPLAY_BUTTON_CHANGE) {
  1786.     if(!AdminRights) {
  1787.       wxMessageBox("You do not have Admin User Privileges\n",
  1788.            "Program Message", wxOK|wxCENTRE);
  1789.       return;
  1790.     }
  1791.     
  1792.     if(dllist->IsEmpty()) {
  1793.       wxMessageBox("The display list is empty\n",
  1794.            "Program Message", wxOK|wxCENTRE);
  1795.       return;
  1796.     }
  1797.  
  1798.     if(!dllist->IsEmpty()) {
  1799.       strdb.ReadObject(dllistptr->Data.object_address);
  1800.       cstrdb->Copy(strdb);
  1801.     }
  1802.     else
  1803.       cstrdb->Copy(*dstrdb);
  1804.     frame->changeText->key->SetValue(cstrdb->GetKM());
  1805.     wxCommandEvent wxevent(wxEVENT_TYPE_BUTTON_COMMAND);
  1806.     ChBtnProc(*btn_ch_sh, wxevent); // Simulate pushing the Search Button
  1807.     CPanelFrame->Show(TRUE); // Show the Change Panel Frame
  1808.   }
  1809.  
  1810.   if(tag == DISPLAY_BUTTON_CLOSE) {
  1811.     ClearDisplayPanel();
  1812.     displaying_list = 0;
  1813.     DPanelFrame->Show(FALSE);
  1814.     CPanelFrame->Show(FALSE);
  1815.     dllist->Clear();
  1816.     return;
  1817.   }
  1818.  
  1819.   if(tag == DISPLAY_BUTTON_REMOVE) {
  1820.     if(!AdminRights) {
  1821.       wxMessageBox("You do not have Admin User Privileges\n",
  1822.            "Program Message", wxOK|wxCENTRE);
  1823.       return;
  1824.     }
  1825.  
  1826.     if(dllist->IsEmpty()) {
  1827.       wxMessageBox("The display list is empty\n",
  1828.            "Program Message", wxOK|wxCENTRE);
  1829.       return;
  1830.     }
  1831.     else
  1832.       Remove(*frame->textWin, dstrdb->GetKM());
  1833.   }
  1834. }
  1835.  
  1836. void ClearDisplayPanel()
  1837. {
  1838.   if(KeyName != 0) frame->displayText->key->SetValue("");
  1839.   if(M2Name != 0) frame->displayText->m2->SetValue("");
  1840.   if(M3Name != 0) frame->displayText->m3->SetValue("");
  1841.   if(M4Name != 0) frame->displayText->m4->SetValue("");
  1842.   if(M5Name != 0) frame->displayText->m5->SetValue("");
  1843.   if(M6Name != 0) frame->displayText->m6->SetValue("");
  1844.   if(M7Name != 0) frame->displayText->m7->SetValue("");
  1845.   if(M8Name != 0) frame->displayText->m8->SetValue("");
  1846.   if(Comments != 0) frame->displayText->cmt->SetValue("");
  1847. }
  1848.  
  1849. void DisplayObject(StrDB &strdb)
  1850. {
  1851.   dstrdb->Copy(strdb); // Initialize global display object
  1852.  
  1853.   if(KeyName != 0)  
  1854.     if(strdb.GetKM())
  1855.       frame->displayText->key->SetValue(strdb.GetKM());
  1856.   if(M2Name != 0)  
  1857.     if(strdb.GetM2())
  1858.       frame->displayText->m2->SetValue(strdb.GetM2());
  1859.   if(M3Name != 0) 
  1860.     if(strdb.GetM3())
  1861.       frame->displayText->m3->SetValue(strdb.GetM3());
  1862.   if(M4Name != 0)  
  1863.     if(strdb.GetM4())
  1864.       frame->displayText->m4->SetValue(strdb.GetM4());
  1865.   if(M5Name != 0)  
  1866.     if(strdb.GetM5())
  1867.       frame->displayText->m5->SetValue(strdb.GetM5());
  1868.   if(M6Name != 0)  
  1869.     if(strdb.GetM6())
  1870.       frame->displayText->m6->SetValue(strdb.GetM6());
  1871.   if(M7Name != 0)  
  1872.     if(strdb.GetM7())
  1873.       frame->displayText->m7->SetValue(strdb.GetM7());
  1874.   if(M8Name != 0)  
  1875.     if(strdb.GetM8())
  1876.       frame->displayText->m8->SetValue(strdb.GetM8());
  1877.   if(Comments != 0)  
  1878.     if(strdb.GetCM())
  1879.       frame->displayText->cmt->SetValue(strdb.GetCM());
  1880.  
  1881.   displaying_list = 1;
  1882.   DPanelFrame->Show(TRUE);
  1883. }
  1884.  
  1885. int LoadIndexKeys()
  1886. {
  1887.   // Clear the doubly linked list
  1888.   dllist->Clear();
  1889.  
  1890.   BtreeWalker btw(DB->Index());
  1891.   unsigned num_objects = btw.Sort(LoadKeys);
  1892.  
  1893.   if(num_objects > 0) print_list = 1;
  1894.   return num_objects;
  1895. }
  1896.  
  1897. void DisplayDB(MyTextWindow &textWin)
  1898. {
  1899.   if(KeyName == 0) return;
  1900.  
  1901.   textWin.Clear();
  1902.   textWin << "Displaying the database objects." << "\n";
  1903.     
  1904.   if(DB->RebuildIndex()) {
  1905.     textWin << "\n";
  1906.     textWin << "The index file needs to be rebuilt." << "\n";
  1907.     return;
  1908.   }
  1909.  
  1910.   num_objects = LoadIndexKeys();
  1911.   
  1912.   if(num_objects == 0) {
  1913.     textWin << "The database is empty." << "\n";
  1914.     dllist->Clear();
  1915.     return;
  1916.   }
  1917.   else
  1918.     textWin << "Displaying " << num_objects << " objects..." << "\n";
  1919.  
  1920.   // Initialize the doubly list node pointer
  1921.   dllistptr = dllist->GetFront();
  1922.   
  1923.   // Display the first object
  1924.   StrDB strdb(DB);
  1925.   strdb.ReadObject(dllistptr->Data.object_address);
  1926.   DisplayObject(strdb);
  1927. }
  1928.  
  1929. void FindBy(MyTextWindow &textWin, const char *MemberName, StrDBItem item)
  1930. {
  1931.   if(MemberName == 0) return;
  1932.  
  1933.   textWin.Clear();
  1934.   textWin << "Searching for object by " << (char *)MemberName << "\n";
  1935.   UString comp;
  1936.  
  1937.   comp = comp + "Enter complete string or use " + WildCard + \
  1938.     " for a wild card:";
  1939.   
  1940.   char *buf = wxGetTextFromUser(comp.c_str(), (char *)MemberName);
  1941.  
  1942.   if(!buf) {
  1943.     textWin << "Canceled." << "\n";
  1944.     return;
  1945.   }
  1946.   UString name(buf);
  1947.   
  1948.   // Remove any leading space from the key name entry
  1949.   unsigned offset = name.Find(" ");
  1950.  
  1951.   if(offset == 0) name.DeleteAt(offset, 1);
  1952.   
  1953.   if(name == "") { // Check for a key name valid input
  1954.     comp.DeleteAt(0, comp.length());
  1955.     comp = comp + "Invalid " + MemberName + " input!";
  1956.     frame->textWin->WriteText(comp.c_str());
  1957.     frame->textWin->WriteText("\n");
  1958.     Error->Message(comp.c_str());
  1959.     return;
  1960.   }
  1961.  
  1962.   if(DB->RebuildIndex()) {
  1963.     textWin << "\n";
  1964.     textWin << "The index file needs to be rebuilt." << "\n";
  1965.     return;
  1966.   }
  1967.   
  1968.   StrDB strdb(DB);
  1969.   
  1970.   offset = name.Find(WildCard); // Look for wild card character
  1971.   if(offset == UString::NoMatch) { // No wild cards found
  1972.     strdb.SetKM(buf);
  1973.     StrDBSearch(strdb, item, name, textWin);
  1974.     return;
  1975.   }
  1976.   else 
  1977.     StrDBSearch(strdb, item, name, textWin, WildCard);
  1978. }
  1979.  
  1980. void StrDBSearch(StrDB &strdb, StrDBItem item, UString &str,
  1981.          MyTextWindow &textWin, const char *wildcard)
  1982. {
  1983.   textWin << "Searching for " << str.c_str() << "\n";
  1984.   int offset;
  1985.   offset = ObjectsFound = 0;
  1986.  
  1987.   if(wildcard != 0) {
  1988.     while(1) { // Remove the wild card characters from the string
  1989.       offset = str.Find(wildcard, offset);
  1990.       if (offset == UString::NoMatch) break;
  1991.       str.DeleteAt(offset, strlen(wildcard));
  1992.       offset++;
  1993.     }
  1994.   }
  1995.  
  1996.   // Ensure that the memory buffers and the file data
  1997.   // stay in sync during multiple file access.
  1998.   DB->Index()->TestTree();
  1999.  
  2000.   dllist->Clear();
  2001.   
  2002.   if(wildcard != 0)
  2003.     BtreeSearch(DB->Index(), item, strdb, str, 1);
  2004.   else
  2005.     BtreeSearch(DB->Index(), item, strdb, str);
  2006.  
  2007.   if(ObjectsFound == 0) {
  2008.     textWin << "No matches found." << "\n";
  2009.     return;
  2010.   }
  2011.   else
  2012.     num_objects = ObjectsFound;
  2013.  
  2014.   dllistptr = dllist->GetFront();
  2015.  
  2016.   UString comp;
  2017.   int yn;
  2018.   
  2019.   if(ObjectsFound > 1) { // Found multiple matches
  2020.     textWin << "Found " << ObjectsFound << " matching." << "\n";
  2021.     char intbuf[100];
  2022.     sprintf(intbuf, "%d", ObjectsFound); 
  2023.     comp = comp + "Found " + intbuf + " matching.\nDisplay the objects?";
  2024.     yn = wxMessageBox(comp.c_str(), "Program Message", wxYES_NO|wxCENTRE);
  2025.   }
  2026.   else {
  2027.     textWin << "Found matching entry for: " << str.c_str() << "\n";
  2028.     comp = comp + "Found matching entry for: " + str +  \
  2029.       "\nDisplay the object?";
  2030.     yn = wxMessageBox(comp.c_str(), "Program Message", wxYES_NO|wxCENTRE);
  2031.   }
  2032.  
  2033.   if(yn == wxNO) {
  2034.     dllist->Clear();
  2035.     num_objects = 0;
  2036.     return;
  2037.   }
  2038.   
  2039.   // Display the first object
  2040.   strdb.ReadObject(dllistptr->Data.object_address);
  2041.   DisplayObject(strdb);
  2042. }
  2043.  
  2044. void ExportToASCII(MyTextWindow &textWin)
  2045. {
  2046.   const char dchar = '\t';   // Text delimiter
  2047.   const char filter = '\t'; // Filter out tabs
  2048.   const char *Fill = "None"; // Fill character string
  2049.   int yn, exports = 0;
  2050.   
  2051.   textWin.Clear();
  2052.   textWin << "Exporting database to ASCII file delimited by tabs..." << "\n";
  2053.  
  2054.   if(DB->RebuildIndex()) {
  2055.     textWin << "\n";
  2056.     textWin << "The index file needs to be rebuilt." << "\n";
  2057.     return;
  2058.   }
  2059.  
  2060.   if(displaying_list) {
  2061.     yn = wxMessageBox("Export display list objects?",
  2062.             "Program Message", wxYES_NO|wxCENTRE);
  2063.   }
  2064.   else {
  2065.     yn = wxNO;
  2066.   }
  2067.   
  2068.   if(yn == wxNO) LoadIndexKeys();
  2069.   if(dllist->IsEmpty()) LoadIndexKeys();
  2070.     
  2071.   char *FileName = wxFileSelector("Export to file:", NULL, NULL, NULL, "*.*");
  2072.   if(FileName) {
  2073. #ifdef wx_msw
  2074.     wxUnix2DosFilename(FileName);
  2075. #endif
  2076.   }
  2077.   else {
  2078.     textWin << "Export canceled." << "\n";
  2079.     return; // No vaild file name
  2080.   }
  2081.   
  2082.   UString sbuf;
  2083.   
  2084.   if(VBDFile::Exists(FileName)) {
  2085.     sbuf = sbuf + "The " + FileName + " file already exists!\nOverwrite it?";
  2086.     yn = wxMessageBox(sbuf.c_str(), "File Exists", wxYES_NO|wxCENTRE);
  2087.  
  2088.     if(yn == wxNO) {
  2089.     textWin << "Export canceled." << "\n";
  2090.     return;
  2091.     }
  2092.   }
  2093.   
  2094.   ofstream stream(FileName, ios::out); // Open file and truncate it
  2095.   textWin << "Exporting database to: " << FileName << "\n";
  2096.   
  2097.   if(!stream) { // Could not open the stream
  2098.     sbuf.DeleteAt(0, sbuf.length());
  2099.     sbuf = sbuf + "Could not write to: " + FileName;
  2100.     textWin << sbuf.c_str() << "\n";
  2101.     Error->Message(sbuf.c_str());
  2102.     return; 
  2103.   }
  2104.  
  2105.   StrDB strdb(DB);
  2106.  
  2107.   // Write the item bar to the file first
  2108.   if(KeyName != 0) {
  2109.     ASPrint(KeyName, stream, strlen(KeyName));
  2110.     stream << dchar;
  2111.   }
  2112.   if(M2Name != 0) {
  2113.     ASPrint(M2Name, stream, strlen(M2Name));
  2114.     stream << dchar;
  2115.   }
  2116.   if(M3Name != 0) {
  2117.     ASPrint(M3Name, stream, strlen(M3Name));
  2118.     stream << dchar;
  2119.   }
  2120.   if(M4Name != 0) {
  2121.     ASPrint(M4Name, stream, strlen(M4Name));
  2122.     stream << dchar;
  2123.   }
  2124.   if(M5Name != 0) {
  2125.     ASPrint(M5Name, stream, strlen(M5Name));
  2126.     stream << dchar;
  2127.   }
  2128.   if(M6Name != 0) {
  2129.     ASPrint(M6Name, stream, strlen(M6Name));
  2130.     stream << dchar;
  2131.   }
  2132.   if(M7Name != 0) {
  2133.     ASPrint(M7Name, stream, strlen(M7Name));
  2134.     stream << dchar;
  2135.   }
  2136.   if(M8Name != 0) {
  2137.     ASPrint(M8Name, stream, strlen(M8Name));
  2138.     stream << dchar;
  2139.   }
  2140.   if(Comments != 0) {
  2141.     ASPrint(Comments, stream, strlen(Comments));
  2142.   }
  2143.   stream << asLineFeed;
  2144.  
  2145.   dllistptr = dllist->GetFront();
  2146.   while(!dllist->IsHeader(dllistptr)) {
  2147.     strdb.ReadObject(dllistptr->Data.object_address);
  2148.     if(KeyName != 0) {
  2149.       ASPrint(strdb.GetKM(), filter, stream, strlen(strdb.GetKM()));
  2150.       stream << dchar;
  2151.     }
  2152.     if(M2Name != 0) {
  2153.       if(!*strdb.GetM2()) ASPrint(Fill, stream, strlen(Fill));
  2154.       else ASPrint(strdb.GetM2(), filter, stream, strlen(strdb.GetM2()));
  2155.       stream << dchar;
  2156.     }
  2157.     if(M3Name != 0) {
  2158.       if(!*strdb.GetM3()) ASPrint(Fill, stream, strlen(Fill));
  2159.       else ASPrint(strdb.GetM3(), filter, stream, strlen(strdb.GetM3()));
  2160.       stream << dchar;
  2161.     }
  2162.     if(M4Name != 0) {
  2163.       if(!*strdb.GetM4()) ASPrint(Fill, stream, strlen(Fill));
  2164.       else ASPrint(strdb.GetM4(), filter, stream, strlen(strdb.GetM4()));
  2165.       stream << dchar;
  2166.     }
  2167.     if(M5Name != 0) {
  2168.       if(!*strdb.GetM5()) ASPrint(Fill, stream, strlen(Fill));
  2169.       else ASPrint(strdb.GetM5(), filter, stream, strlen(strdb.GetM5()));
  2170.       stream << dchar;
  2171.     }
  2172.     if(M6Name != 0) {
  2173.       if(!*strdb.GetM6()) ASPrint(Fill, stream, strlen(Fill));
  2174.       else ASPrint(strdb.GetM6(), filter, stream, strlen(strdb.GetM6()));
  2175.       stream << dchar;
  2176.     }
  2177.     if(M7Name != 0) {
  2178.       if(!*strdb.GetM7()) ASPrint(Fill, stream, strlen(Fill));
  2179.       else ASPrint(strdb.GetM7(), filter, stream, strlen(strdb.GetM7()));
  2180.       stream << dchar;
  2181.     }
  2182.     if(M8Name != 0) {
  2183.       if(!*strdb.GetM8()) ASPrint(Fill, stream, strlen(Fill));
  2184.       else ASPrint(strdb.GetM8(), filter, stream, strlen(strdb.GetM8()));
  2185.       stream << dchar;
  2186.     }
  2187.     if(Comments != 0) {
  2188.       if(!*strdb.GetCM()) ASPrint(Fill, stream, strlen(Fill));
  2189.       else ASPrint(strdb.GetCM(), filter, stream, strlen(strdb.GetCM()));
  2190.     }
  2191.     stream << asLineFeed;
  2192.     exports++;
  2193.     dllistptr = dllistptr->GetNext();
  2194.   }
  2195.   textWin << "Exported " << exports << " objects." << "\n";
  2196.   stream.close();
  2197. }
  2198.  
  2199. void ImportFromASCII(MyTextWindow &textWin)
  2200. {
  2201.   if(KeyName == 0) return;
  2202.  
  2203.   if(!AdminRights) {
  2204.     wxMessageBox("You do not have Admin User Privileges\n",
  2205.          "Program Message", wxOK|wxCENTRE);
  2206.     return;
  2207.   }
  2208.   
  2209.   char words[MAXWORDS][MAXWORDLENGTH];
  2210.   int num;
  2211.   const int MaxLine = 512;
  2212.   char LineBuffer[MaxLine];
  2213.   UString sbuf;
  2214.   const char dchar = '\t';  // Text delimiter
  2215.  
  2216.   // wxWindows single choice index box setup
  2217.   int ch = -1;
  2218.   const int CHArray = 4; 
  2219.   
  2220.   char *ch_array[CHArray] = {
  2221.     "Update this entry",
  2222.     "Skip this entry",
  2223.     "Update all entries without prompting",
  2224.     "Quit this import"
  2225.   };
  2226.  
  2227.   enum ICHOICES {
  2228.     UPDATE_ENTRY,
  2229.     UPDATE_SKIP,
  2230.     UPDATE_ALL,
  2231.     QUIT_THIS
  2232.   };
  2233.   
  2234.   textWin.Clear();
  2235.   textWin << "Importing database from ASCII file delimited by tabs..." << "\n";
  2236.  
  2237.   char *FileName = wxFileSelector("Import from file:",
  2238.                   NULL, NULL, NULL, "*.*");
  2239.   if(FileName) {
  2240. #ifdef wx_msw
  2241.     wxUnix2DosFilename(FileName);
  2242. #endif
  2243.   }
  2244.   else {
  2245.     textWin << "Import canceled." << "\n";
  2246.     return; // No vaild file name
  2247.   }
  2248.  
  2249.   ifstream stream(FileName, ios::in|ios::nocreate);
  2250.   textWin << "Importing database from: " << FileName << "\n";
  2251.   
  2252.   if(!stream) { // Could not open the stream
  2253.     textWin << "Could not open file: " << FileName << "\n";
  2254.     return; 
  2255.   }
  2256.  
  2257.   textWin << "Importing..." << "\n";
  2258.  
  2259.   SNode<UString> *sllistptr; // Linked list node pointer
  2260.   SLList<UString> sllist;    // Linked list
  2261.  
  2262.   while(!stream.eof())
  2263.   {
  2264.     // Read in file line by line
  2265.     stream.getline(LineBuffer, MaxLine);
  2266.  
  2267.     // Copy contents of the array to temporary holding buffer
  2268.     sbuf = LineBuffer;
  2269.  
  2270.     // Load file data into singly-linked list
  2271.     sllistptr = sllist.StoreNode(sbuf); 
  2272.  
  2273.     // Clear the string buffer
  2274.     sbuf.DeleteAt(0, sbuf.length());
  2275.     
  2276.     if(!sllistptr) { // Out of memory
  2277.       stream.close();
  2278.       sllist.Clear();
  2279.       return;
  2280.    }
  2281.   }
  2282.   stream.close();
  2283.   
  2284.   StrDB strdb(DB);
  2285.   StrDB strdba(DB);
  2286.   StrDB ob(DB);
  2287.  
  2288.   int linecount = 0;
  2289.   int imports = 0;
  2290.   int updates = 0;
  2291.   int updateall = 0;
  2292.   int ObjectItems = 1; // Number of class data members 
  2293.  
  2294.   // Calculate the number of objects 
  2295.   if(M2Name != 0) ObjectItems++;
  2296.   if(M3Name != 0) ObjectItems++;
  2297.   if(M4Name != 0) ObjectItems++;
  2298.   if(M5Name != 0) ObjectItems++;
  2299.   if(M6Name != 0) ObjectItems++;
  2300.   if(M7Name != 0) ObjectItems++;
  2301.   if(M8Name != 0) ObjectItems++;
  2302.   if(Comments != 0) ObjectItems++;
  2303.  
  2304.   sllistptr = sllist.GetFront();
  2305.   while(!sllist.IsHeader(sllistptr)) {
  2306.     if(parse(sllistptr->Data.c_str(), words, &num, dchar) == 1) {
  2307.       textWin << "Parse error!" << "\n";
  2308.       break;
  2309.     }
  2310.  
  2311.     linecount++;
  2312.     if(num != ObjectItems && (num != 0 && num != 1)) {
  2313.       textWin << "Error in " << FileName << " import file!" << "\n";
  2314.       if(num > ObjectItems) 
  2315.     textWin << "To many items on line: ";
  2316.       if(num < ObjectItems) 
  2317.     textWin << "Not enough items on line: ";
  2318.       textWin << linecount << "\n";
  2319.       int yn = wxMessageBox("Error in import file! Continue?",
  2320.                 "Program Message", wxYES_NO|wxCENTRE);
  2321.       if(yn == wxNO) {
  2322.       sllist.Clear();
  2323.       return;
  2324.       }
  2325.     }
  2326.     
  2327.     if(num == ObjectItems && *words[0] != 0) {
  2328.       strdb.SetKM(words[0]);
  2329.       if(M2Name != 0) strdb.SetM2(words[1]);
  2330.       if(M3Name != 0) strdb.SetM3(words[2]);
  2331.       if(M4Name != 0) strdb.SetM4(words[3]);
  2332.       if(M5Name != 0) strdb.SetM5(words[4]);
  2333.       if(M6Name != 0) strdb.SetM6(words[5]);
  2334.       if(M7Name != 0) strdb.SetM7(words[6]);
  2335.       if(M8Name != 0) strdb.SetM8(words[7]);
  2336.       if(Comments != 0) strdb.SetCM(words[8]);
  2337.       
  2338.       strdba.SetKM(strdb.GetKM());
  2339.       FAU addr = strdba.FindObject();
  2340.       
  2341.       if(addr) {
  2342.     if(updateall == 0) {
  2343.       sbuf.DeleteAt(0, sbuf.length());
  2344.       sbuf = sbuf + strdb.GetKM() + " entry already exists.\n" + \
  2345.         "Select your choice and click on OK";
  2346.       ch = wxGetSingleChoiceIndex(sbuf.c_str(), "Importing Objects",
  2347.                       CHArray, ch_array, frame);
  2348.     }
  2349.     if(updateall == 1) ch = UPDATE_ALL;
  2350.     switch(ch) {
  2351.       case UPDATE_ALL:
  2352.         updateall = 1;
  2353.         updates++;
  2354.         ob.Copy(strdba);
  2355.             if(strdb.FullCompare(ob)) break; // The object has not changed
  2356.         ob.DeleteObject(); 
  2357.             strdb.AddObject(0);
  2358.         sbuf.DeleteAt(0, sbuf.length());
  2359.         sbuf = sbuf + "Updating entry for: " + strdb.GetKM();
  2360.         textWin << sbuf.c_str() << "\n";
  2361.         frame->SetStatusText(sbuf.c_str());
  2362.         break;
  2363.       case UPDATE_SKIP:
  2364.         break;
  2365.       case UPDATE_ENTRY:
  2366.         updates++;
  2367.         ob.Copy(strdba);
  2368.             if(strdb.FullCompare(ob)) break; // The object has not changed
  2369.         ob.DeleteObject(); 
  2370.             strdb.AddObject(0);
  2371.         sbuf.DeleteAt(0, sbuf.length());
  2372.         sbuf = sbuf + "Updating entry for: " + strdb.GetKM();
  2373.         textWin << sbuf.c_str() << "\n";
  2374.         frame->SetStatusText(sbuf.c_str());
  2375.         break;
  2376.       case QUIT_THIS:
  2377.         textWin << "Import cancled." << "\n";
  2378.         textWin << "Imported " << imports << " objects." << "\n";
  2379.         if(updates) {
  2380.           textWin << "Updated " << updates << " objects." << "\n";
  2381.         }
  2382.         sllist.Clear();
  2383.         return;
  2384.       default:
  2385.         break;
  2386.     }
  2387.     if(updateall == 1) {
  2388.       sbuf.DeleteAt(0, sbuf.length());
  2389.       sbuf = sbuf + "Updating entry for: " + strdb.GetKM();
  2390.       textWin << sbuf.c_str() << "\n";
  2391.       frame->SetStatusText(sbuf.c_str());
  2392.     }
  2393.     else {
  2394.       // Nothing to do
  2395.     }
  2396.       }
  2397.       else {
  2398.     // Ensure that the template does not get added to the file
  2399.     if(CaseICmp(KeyName, words[0]) != 0) {
  2400.       FAU addr = strdb.AddObject(0); // Write the object to the file
  2401.       imports++;
  2402.       if(!addr) {
  2403.         textWin << "Could not add:" << strdb.GetKM()
  2404.             << " to database" << "\n";
  2405.         imports--;
  2406.       }
  2407.     }
  2408.       }
  2409.     }
  2410.     sllistptr = sllistptr->GetNext();
  2411.   }
  2412.  
  2413.   textWin << "Imported " << imports << " objects." << "\n";
  2414.   if(updates) {
  2415.     textWin << "Updated " << updates << " objects." << "\n";
  2416.   }
  2417.  
  2418.   sllist.Clear();
  2419. }
  2420.  
  2421. void BackUp(MyTextWindow &textWin)
  2422. {
  2423.   textWin.Clear();
  2424.   textWin << "Backing up the database to another file..." << "\n";
  2425.  
  2426.   char *FileName = wxFileSelector("Backup to file:",
  2427.                   NULL, NULL, NULL, "*.*");
  2428.   if(FileName) {
  2429. #ifdef wx_msw
  2430.     wxUnix2DosFilename(FileName);
  2431. #endif
  2432.   }
  2433.   else {
  2434.     textWin << "Backup canceled." << "\n";
  2435.     return; // No vaild file name
  2436.   }
  2437.   
  2438.   UString sbuf;
  2439.  
  2440.   if(VBDFile::Exists(FileName)) {
  2441.     sbuf = sbuf + "The " + FileName + " file already exists!\nOverwrite it?";
  2442.     int yn = wxMessageBox(sbuf.c_str(), "File Exists", wxYES_NO|wxCENTRE);
  2443.  
  2444.     if(yn == wxNO) {
  2445.     textWin << "Export canceled." << "\n";
  2446.     return;
  2447.     }
  2448.  
  2449.     if(!wxRemoveFile(FileName)) {
  2450.       sbuf.DeleteAt(0, sbuf.length());
  2451.       sbuf = sbuf + "Could not write to: " + FileName;
  2452.       textWin << sbuf.c_str() << "\n";
  2453.       Error->Message(sbuf.c_str());
  2454.       return; 
  2455.     }
  2456.   }
  2457.  
  2458.   POD newdb(FileName, FileName);
  2459.   int items = 0;
  2460.   StrDB strdb(&newdb);
  2461.   StrDB strdb_old(DB);
  2462.   
  2463.   if(DB->RebuildIndex()) {
  2464.     textWin << "\n";
  2465.     textWin << "The index file needs to be rebuilt." << "\n";
  2466.     return;
  2467.   }
  2468.  
  2469.   CachePointer nxt(*DB->Index()->GetCache());
  2470.   BtreeWalkerb tw(DB->Index(), btINORDER);
  2471.   nxt = DB->Index()->GetRoot();
  2472.  
  2473.   while((__LWORD__)nxt != 0) {
  2474.     nxt = tw.Next();
  2475.     if((__LWORD__)nxt) {
  2476.       for(int i = 0; i < nxt->cnt; i++) {
  2477.     strdb_old.ReadObject(nxt->entry[i].object_address);
  2478.     strdb.Copy(strdb_old);
  2479.     strdb.AddObject(0);
  2480.     items++;
  2481.       }
  2482.     }
  2483.   }
  2484.   textWin << "Backed up " << items << " objects to " << FileName << "\n";
  2485. }
  2486.  
  2487. void Merge(MyTextWindow &textWin)
  2488. {
  2489.   if(!AdminRights) {
  2490.     wxMessageBox("You do not have Admin User Privileges\n",
  2491.          "Program Message", wxOK|wxCENTRE);
  2492.     return;
  2493.   }
  2494.   
  2495.   // wxWindows single choice index box setup
  2496.   int ch = -1;
  2497.   const int CHArray = 4; 
  2498.   
  2499.   char *ch_array[CHArray] = {
  2500.     "Update this entry",
  2501.     "Skip this entry",
  2502.     "Update all entries without prompting",
  2503.     "Quit this merge"
  2504.   };
  2505.  
  2506.   enum ICHOICES {
  2507.     UPDATE_ENTRY,
  2508.     UPDATE_SKIP,
  2509.     UPDATE_ALL,
  2510.     QUIT_THIS
  2511.   };
  2512.   
  2513.   textWin.Clear();
  2514.   textWin << "Merging the contents of another database..." << "\n";
  2515.  
  2516.   char *FileName = wxFileSelector("Merge from file:", NULL, NULL, NULL, "*.*");
  2517.   if(FileName) {
  2518. #ifdef wx_msw
  2519.     wxUnix2DosFilename(FileName);
  2520. #endif
  2521.   }
  2522.   else {
  2523.     textWin << "Merge canceled." << "\n";
  2524.     return; // No vaild file name
  2525.   }
  2526.   
  2527.   POD newdb(FileName, FileName);
  2528.   StrDB strdb(&newdb);
  2529.   StrDB strdba(DB);
  2530.   StrDB ob(DB);
  2531.   FAU existing;
  2532.   FAU addr;
  2533.   UString sbuf;
  2534.  
  2535.   int imports = 0;
  2536.   int updates = 0;
  2537.   int updateall = 0;
  2538.   
  2539.   FAU oa;          // Object Address
  2540.   VBlockHeader vb;     // Variable Block Header
  2541.   ObjectHeader oh; // Object Header
  2542.  
  2543.   FAU vbdfileEOF = newdb.OpenDatabase()->GetEOF();
  2544.   
  2545.   addr = 0;
  2546.   addr = newdb.OpenDatabase()->FindFirstVB(addr); // Search the entire file
  2547.  
  2548.   if(addr == 0) {
  2549.     textWin << "No variable blocks found in file: " << FileName << "\n";
  2550.     return;
  2551.   }
  2552.  
  2553.   textWin << "Merging..." << "\n";
  2554.  
  2555.   while(1) { 
  2556.     if(addr >= vbdfileEOF) break;
  2557.     newdb.OpenDatabase()->Read(&vb, sizeof(VBlockHeader), addr);
  2558.     if(vb.CkWord == CheckWord) {
  2559.       if((__SBYTE__)vb.VBStatus == NormalVB) {
  2560.     oa = addr + sizeof(VBlockHeader);
  2561.     newdb.OpenDatabase()->Read(&oh, sizeof(ObjectHeader), oa);
  2562.     if(oh.ClassID == strdb.GetClassID()) { 
  2563.       strdb.ReadObject(oa);
  2564.       strdba.SetKM(strdb.GetKM());
  2565.       existing = strdba.FindObject();
  2566.       if(existing) {
  2567.         if(updateall == 0) {
  2568.           sbuf.DeleteAt(0, sbuf.length());
  2569.           sbuf = sbuf +  strdba.GetKM() + " entry already exists.\n" + \
  2570.         "Select your choice and click on OK"; 
  2571.           ch = wxGetSingleChoiceIndex(sbuf.c_str(), "Importing Objects",
  2572.                       CHArray, ch_array, frame);
  2573.         }
  2574.         if(updateall == 1) ch = UPDATE_ALL;
  2575.         switch(ch) {
  2576.           case UPDATE_ALL:
  2577.         updateall = 1;
  2578.         updates++;
  2579.         ob.Copy(strdb);
  2580.         if(strdb.FullCompare(ob)) break; // The object has not changed
  2581.         ob.DeleteObject(); 
  2582.         ob.Copy(strdb);
  2583.         ob.AddObject(0);
  2584.         sbuf.DeleteAt(0, sbuf.length());
  2585.         sbuf = sbuf  + "Updating entry for: " + strdb.GetKM();
  2586.         textWin << sbuf.c_str() << "\n";
  2587.         frame->SetStatusText(sbuf.c_str());
  2588.         break;
  2589.           case UPDATE_SKIP:
  2590.         break;
  2591.           case UPDATE_ENTRY:
  2592.         updates++;
  2593.         ob.Copy(strdb);
  2594.         if(strdb.FullCompare(ob)) break; // The object has not changed
  2595.         ob.DeleteObject(); 
  2596.         ob.Copy(strdb);
  2597.         ob.AddObject(0);
  2598.         sbuf.DeleteAt(0, sbuf.length());
  2599.         sbuf = sbuf + "Updating entry for: " + strdb.GetKM();
  2600.         textWin << sbuf.c_str() << "\n";
  2601.         frame->SetStatusText(sbuf.c_str());
  2602.         break;
  2603.           case QUIT_THIS:
  2604.         textWin << "Merge cancled." << "\n";
  2605.         textWin << "Imported " << imports << " objects." << "\n";
  2606.         if(updates) {
  2607.           textWin << "Updated " << updates << " objects." << "\n";
  2608.         }
  2609.         return;
  2610.           default:
  2611.         break;
  2612.         }
  2613.         if(updateall == 1) {
  2614.           sbuf.DeleteAt(0, sbuf.length());
  2615.           sbuf = sbuf + "Updating entry for: " + strdb.GetKM();
  2616.           textWin << sbuf.c_str() << "\n";
  2617.           frame->SetStatusText(sbuf.c_str());
  2618.         }
  2619.         else {
  2620.           // Nothing to do
  2621.         }
  2622.       }
  2623.       else {
  2624.         strdba.Copy(strdb);
  2625.         FAU rvaddr = strdba.AddObject(0); // Write the object to the file
  2626.         imports++;
  2627.         if(!rvaddr) {
  2628.           textWin << "Could not add:" << strdb.GetKM()
  2629.               << " to database" << "\n";
  2630.           imports--;
  2631.         }
  2632.         
  2633.       }
  2634.     }
  2635.     
  2636.       }
  2637.       addr = addr + vb.Length; // Goto the next variable block
  2638.     }
  2639.     else {
  2640.       addr = newdb.OpenDatabase()->VBSearch(addr); 
  2641.       if(!addr) break;
  2642.     }
  2643.   }
  2644.   
  2645.   textWin << "Imported " << imports << " objects." << "\n";
  2646.   if(updates) {
  2647.     textWin << "Updated " << updates << " objects." << "\n";
  2648.   }
  2649. }
  2650.  
  2651. void CreateTemplate(MyTextWindow &textWin)
  2652. {
  2653.   const char dchar = '\t';   // Text delimiter
  2654.  
  2655.   textWin.Clear();
  2656.   textWin << "Creating template file delimited by tabs..." << "\n";
  2657.  
  2658.  
  2659.   char *FileName = wxFileSelector("Template file to create:",
  2660.                   NULL, NULL, NULL, "*.*");
  2661.   if(FileName) {
  2662. #ifdef wx_msw
  2663.     wxUnix2DosFilename(FileName);
  2664. #endif
  2665.   }
  2666.   else {
  2667.     textWin << "Creating template canceled." << "\n";
  2668.     return; // No vaild file name
  2669.   }
  2670.   
  2671.   UString sbuf;
  2672.   
  2673.   if(VBDFile::Exists(FileName)) {
  2674.     sbuf = sbuf + "The " + FileName + " file already exists!\nOverwrite it?";
  2675.     int yn = wxMessageBox(sbuf.c_str(), "File Exists", wxYES_NO|wxCENTRE);
  2676.  
  2677.     if(yn == wxNO) {
  2678.     textWin << "Creating template canceled." << "\n";
  2679.     return;
  2680.     }
  2681.   }
  2682.   
  2683.   ofstream stream(FileName, ios::out); // Open file and truncate it
  2684.   textWin << "Creating template file: " << FileName << "\n";
  2685.  
  2686.     if(!stream) { // Could not open the stream
  2687.       sbuf.DeleteAt(0, sbuf.length());
  2688.       sbuf = sbuf  + "Could not write to: " + FileName;
  2689.       textWin << sbuf.c_str() << "\n";
  2690.       Error->Message(sbuf.c_str());
  2691.       return; 
  2692.     }
  2693.  
  2694.   if(KeyName != 0) {
  2695.     ASPrint(KeyName, stream, strlen(KeyName));
  2696.     stream << dchar;
  2697.   }
  2698.   if(M2Name != 0) {
  2699.     ASPrint(M2Name, stream, strlen(M2Name));
  2700.     stream << dchar;
  2701.   }
  2702.   if(M3Name != 0) {
  2703.     ASPrint(M3Name, stream, strlen(M3Name));
  2704.     stream << dchar;
  2705.   }
  2706.   if(M4Name != 0) {
  2707.     ASPrint(M4Name, stream, strlen(M4Name));
  2708.     stream << dchar;
  2709.   }
  2710.   if(M5Name != 0) {
  2711.     ASPrint(M5Name, stream, strlen(M5Name));
  2712.     stream << dchar;
  2713.   }
  2714.   if(M6Name != 0) {
  2715.     ASPrint(M6Name, stream, strlen(M6Name));
  2716.     stream << dchar;
  2717.   }
  2718.   if(M7Name != 0) {
  2719.     ASPrint(M7Name, stream, strlen(M7Name));
  2720.     stream << dchar;
  2721.   }
  2722.   if(M8Name != 0) {
  2723.     ASPrint(M8Name, stream, strlen(M8Name));
  2724.     stream << dchar;
  2725.   }
  2726.   if(Comments != 0) {
  2727.     ASPrint(Comments, stream, strlen(Comments));
  2728.   }
  2729.   stream << asLineFeed;
  2730.   
  2731.   textWin << "Finished." << "\n";
  2732.   stream.close();
  2733. }
  2734.  
  2735. void ASCIIPrintAll(MyTextWindow &textWin)
  2736. {
  2737.   ASCIIPrint(PORTRAIT, textWin);
  2738. }
  2739.  
  2740. void ASCIIPrintAllLong(MyTextWindow &textWin)
  2741. {
  2742.   ASCIIPrint(LANDSCAPE, textWin);
  2743. }
  2744.  
  2745. int ASCIIPrint(PrintMode mode, MyTextWindow &textWin)
  2746. {
  2747.   textWin.Clear();
  2748.   textWin << "Printing database to ASCII file..." << "\n";
  2749.   int yn = 0;
  2750.   
  2751.   if(DB->RebuildIndex()) {
  2752.     textWin << "\n";
  2753.     textWin << "The index file needs to be rebuilt." << "\n";
  2754.     return 0;
  2755.   }
  2756.  
  2757.   if(displaying_list) {
  2758.     yn = wxMessageBox("Print display list objects?",
  2759.               "Program Message", wxYES_NO|wxCENTRE);
  2760.   }
  2761.   else {
  2762.     yn = wxNO;
  2763.   }
  2764.   
  2765.   if(yn == wxNO) LoadIndexKeys();
  2766.   if(dllist->IsEmpty()) LoadIndexKeys();
  2767.   
  2768.   char *FileName = wxFileSelector("Print database to file:",
  2769.                   NULL, NULL, NULL, "*.*");
  2770.   if(FileName) {
  2771. #ifdef wx_msw
  2772.     wxUnix2DosFilename(FileName);
  2773. #endif
  2774.   }
  2775.   else {
  2776.     textWin << "ASCII print canceled." << "\n";
  2777.     return 0; // No vaild file name
  2778.   }
  2779.   
  2780.   UString sbuf;
  2781.   
  2782.   if(VBDFile::Exists(FileName)) {
  2783.     sbuf = sbuf + "The " + FileName + " file already exists!\nOverwrite it?";
  2784.     yn = wxMessageBox(sbuf.c_str(), "File Exists", wxYES_NO|wxCENTRE);
  2785.  
  2786.     if(yn == wxNO) {
  2787.       textWin << "ASCII print canceled." << "\n";
  2788.       return 0;
  2789.     }
  2790.   }
  2791.   
  2792.   ofstream stream(FileName, ios::out); // Open file and truncate it
  2793.   textWin << "Printing to: " << FileName << "\n";
  2794.   
  2795.   if(!stream) { // Could not open the stream
  2796.     sbuf.DeleteAt(0, sbuf.length());
  2797.     sbuf = sbuf + "Could not write to: " + FileName;
  2798.     textWin << sbuf.c_str() << "\n";
  2799.     Error->Message(sbuf.c_str());
  2800.     return 0; 
  2801.   }
  2802.           
  2803.   StrDB strdb(DB);
  2804.   unsigned count = 0;
  2805.  
  2806.   if(mode == LANDSCAPE)
  2807.     PrintItemBar(stream, 0);
  2808.   else
  2809.     PrintItemBar(stream);
  2810.  
  2811.   dllistptr = dllist->GetFront();
  2812.   textWin << "Printing..." << "\n";
  2813.   while(!dllist->IsHeader(dllistptr)) {
  2814.     strdb.ReadObject(dllistptr->Data.object_address);
  2815.     switch(mode) {
  2816.       case PORTRAIT: 
  2817.     PrintLineByLine(strdb, stream);
  2818.     break;
  2819.       case LANDSCAPE: 
  2820.     PrintLineByLine(strdb, stream, 0);          
  2821.     break;
  2822.       default:
  2823.     return 0;
  2824.     }
  2825.     count++; 
  2826.     dllistptr = dllistptr->GetNext();
  2827.   }
  2828.  
  2829.   textWin << "Finished." << "\n";
  2830.   stream.close();
  2831.   return count;
  2832. }
  2833.  
  2834. void PrintItemBar(ofstream &stream, int abv)
  2835. {
  2836.   int i = 0;
  2837.   if(KeyName != 0) ASPrint(KeyName, stream, StringOffset+1);
  2838.   if(M2Name != 0) ASPrint(M2Name, stream, StringOffset+1);
  2839.   if(M3Name != 0) ASPrint(M3Name, stream, StringOffset+1);
  2840.   if(M4Name != 0) ASPrint(M4Name, stream, StringOffset+1);
  2841.   if(abv) { // Print abbreviated list for portrait print outs
  2842.     if(M5Name != 0) ASPrint(M5Name, stream, StringOffset);
  2843.     stream << asLineFeed;
  2844.     i = 0;
  2845.     while (i++ < asPrintCols-1) stream << '=';
  2846.     stream << asLineFeed;
  2847.     return;
  2848.   }
  2849.   else { // Print full listing for landscape print outs
  2850.     if(M5Name != 0) ASPrint(M5Name, stream, StringOffset+1);
  2851.     if(M6Name != 0) ASPrint(M6Name, stream, StringOffset+1);
  2852.     if(M7Name != 0) ASPrint(M7Name, stream, StringOffset+1);
  2853.     if(M8Name != 0) ASPrint(M8Name, stream, StringOffset);
  2854.     stream << asLineFeed;
  2855.     i = 0;
  2856.     while (i++ < asPrintColsLong-1) stream << '=';
  2857.     stream << asLineFeed;
  2858.   }
  2859. }
  2860.  
  2861. void PrintLineByLine(StrDB &strdb, ofstream &stream, int abv)
  2862. {
  2863.   int i = 0;
  2864.   
  2865.   if(KeyName != 0) ASPrint(strdb.GetKM(), stream, StringOffset+1);
  2866.   if(M2Name != 0) ASPrint(strdb.GetM2(), stream, StringOffset+1);
  2867.   if(M3Name != 0) ASPrint(strdb.GetM3(), stream, StringOffset+1);
  2868.   if(M4Name != 0) ASPrint(strdb.GetM4(), stream, StringOffset+1);
  2869.   if(abv) { // Print abbreviated list for portrait print outs
  2870.     if(M5Name != 0) ASPrint(strdb.GetM5(), stream, StringOffset);
  2871.     stream << asLineFeed;
  2872.     i = 0;
  2873.     while (i++ < asPrintCols-1) stream << '-';
  2874.     stream << asLineFeed;
  2875.     return;
  2876.   }
  2877.   else { // Print full listing for landscape print outs
  2878.     if(M5Name != 0) ASPrint(strdb.GetM5(), stream, StringOffset+1);
  2879.     if(M6Name != 0) ASPrint(strdb.GetM6(), stream, StringOffset+1);
  2880.     if(M7Name != 0) ASPrint(strdb.GetM7(), stream, StringOffset+1);
  2881.     if(M8Name != 0) ASPrint(strdb.GetM8(), stream, StringOffset);
  2882.     stream << asLineFeed;
  2883.     i = 0;
  2884.     while (i++ < asPrintColsLong-1) stream << '-';
  2885.     stream << asLineFeed;
  2886.   }
  2887. }
  2888.  
  2889. void ASCIIPrintObject(MyTextWindow &textWin, char *keyNM)
  2890. {
  2891.   if(KeyName == 0) return;
  2892.   
  2893.   textWin.Clear();
  2894.   textWin << "Printing object to ASCII file..." << "\n";
  2895.  
  2896.   UString key_name;
  2897.   UString comp;
  2898.   char *buf;
  2899.   
  2900.   if(!keyNM) {
  2901.     comp = comp + "Enter " + KeyName + " to print:"; 
  2902.     buf = wxGetTextFromUser(comp.c_str(), "String Input");
  2903.  
  2904.     if(!buf) {
  2905.       textWin << "Canceled." << "\n";
  2906.       return;
  2907.     }
  2908.  
  2909.     key_name = buf;
  2910.     
  2911.     // Remove any leading space from the key name entry
  2912.     int offset = key_name.Find(" ");
  2913.     if(offset == 0) key_name.DeleteAt(offset, 1);
  2914.   
  2915.     if(key_name == "") { // Check for a key name valid input
  2916.       comp.DeleteAt(0, comp.length());
  2917.       comp = comp + "Invalid " + KeyName + " input!";
  2918.       frame->textWin->WriteText(comp.c_str());
  2919.       frame->textWin->WriteText("\n");
  2920.       Error->Message(comp.c_str());
  2921.       return;
  2922.     }
  2923.   }  
  2924.   else
  2925.     key_name = keyNM; // Key name memeber
  2926.  
  2927.   StrDB strdb(DB);
  2928.   strdb.SetKM(key_name);
  2929.   FAU addr = strdb.FindObject();
  2930.  
  2931.   if(!addr) { 
  2932.     comp.DeleteAt(0, comp.length());
  2933.     comp = comp + "Could not find an entry for: " + key_name.c_str();
  2934.     Error->Message(comp.c_str());
  2935.     textWin << comp.c_str() << "\n";
  2936.     return;
  2937.   }
  2938.  
  2939.   PrintObject(strdb, textWin);
  2940. }
  2941.  
  2942. void PrintObject(StrDB &strdb, MyTextWindow &textWin)
  2943. {
  2944.   const char *separator = " = ";
  2945.   const char *cseparator = ": ";
  2946.  
  2947.   char *FileName = wxFileSelector("Printing object to file:",
  2948.                   NULL, NULL, NULL, "*.*");
  2949.   if(FileName) {
  2950. #ifdef wx_msw
  2951.     wxUnix2DosFilename(FileName);
  2952. #endif
  2953.   }
  2954.   else {
  2955.     textWin << "ASCII print canceled." << "\n";
  2956.     return; // No vaild file name
  2957.   }
  2958.   
  2959.   UString sbuf;
  2960.   
  2961.   if(VBDFile::Exists(FileName)) {
  2962.     sbuf = sbuf + "The " + FileName + " file already exists!\nOverwrite it?";
  2963.     int yn = wxMessageBox(sbuf.c_str(), "File Exists", wxYES_NO|wxCENTRE);
  2964.  
  2965.     if(yn == wxNO) {
  2966.     textWin << "ASCII print canceled." << "\n";
  2967.     return;
  2968.     }
  2969.   }
  2970.   
  2971.   ofstream stream(FileName, ios::out); // Open file and truncate it
  2972.   textWin << "Printing to: " << FileName << "\n";
  2973.  
  2974.   if(!stream) { // Could not open the stream
  2975.     sbuf.DeleteAt(0, sbuf.length());
  2976.     sbuf = sbuf + "Could not write to: " + FileName;
  2977.     textWin << sbuf.c_str() << "\n";
  2978.     Error->Message(sbuf.c_str());
  2979.     return; 
  2980.   }
  2981.  
  2982.   if(KeyName != 0) {
  2983.     ASPrint(KeyName, stream, strlen(KeyName));
  2984.     ASPrint(separator, stream, strlen(separator));
  2985.     ASPrint(strdb.GetKM(), stream, strlen(strdb.GetKM()));
  2986.     stream << asLineFeed;
  2987.   }
  2988.   if(M2Name != 0) {
  2989.     ASPrint(M2Name, stream, strlen(M2Name));
  2990.     ASPrint(separator, stream, strlen(separator));
  2991.     ASPrint(strdb.GetM2(), stream, strlen(strdb.GetM2()));
  2992.     stream << asLineFeed;
  2993.   }
  2994.   if(M3Name != 0) {
  2995.     ASPrint(M3Name, stream, strlen(M3Name));
  2996.     ASPrint(separator, stream, strlen(separator));
  2997.     ASPrint(strdb.GetM3(), stream, strlen(strdb.GetM3()));
  2998.     stream << asLineFeed;
  2999.   }
  3000.   if(M4Name != 0) {
  3001.     ASPrint(M4Name, stream, strlen(M4Name));
  3002.     ASPrint(separator, stream, strlen(separator));
  3003.     ASPrint(strdb.GetM4(), stream, strlen(strdb.GetM4()));
  3004.     stream << asLineFeed;
  3005.   }
  3006.   if(M5Name != 0) {
  3007.     ASPrint(M5Name, stream, strlen(M5Name));
  3008.     ASPrint(separator, stream, strlen(separator));
  3009.     ASPrint(strdb.GetM5(), stream, strlen(strdb.GetM5()));
  3010.     stream << asLineFeed;
  3011.   }
  3012.   if(M6Name != 0) {
  3013.     ASPrint(M6Name, stream, strlen(M6Name));
  3014.     ASPrint(separator, stream, strlen(separator));
  3015.     ASPrint(strdb.GetM6(), stream, strlen(strdb.GetM6()));
  3016.     stream << asLineFeed;
  3017.   }
  3018.   if(M7Name != 0) {
  3019.     ASPrint(M7Name, stream, strlen(M7Name));
  3020.     ASPrint(separator, stream, strlen(separator));
  3021.     ASPrint(strdb.GetM7(), stream, strlen(strdb.GetM7()));
  3022.     stream << asLineFeed;
  3023.   }
  3024.   if(M8Name != 0) {
  3025.     ASPrint(M8Name, stream, strlen(M8Name));
  3026.     ASPrint(separator, stream, strlen(separator));
  3027.     ASPrint(strdb.GetM8(), stream, strlen(strdb.GetM8()));
  3028.     stream << asLineFeed;
  3029.   }
  3030.   if(Comments != 0) {
  3031.     ASPrint(Comments, stream, strlen(Comments));
  3032.     ASPrint(cseparator, stream, strlen(cseparator));
  3033.     ASPrint(strdb.GetCM(), stream, strlen(strdb.GetCM()));
  3034.     stream << asLineFeed;
  3035.   }
  3036.  
  3037.   textWin << "Finished." << "\n";
  3038.   stream.close();
  3039. }
  3040.  
  3041. void CompareIndexFile(MyTextWindow &textWin)
  3042. {
  3043.   textWin.Clear();
  3044.   textWin << "Comparing the index file to the data file..." << "\n";
  3045.   
  3046.   StrDB strdb(DB);
  3047.   int rv = strdb.CompareIndex();
  3048.   if(!rv) {
  3049.     textWin << "The index file does not match the data file!" << "\n";
  3050.     textWin << "The index file needs to be rebuilt." << "\n";
  3051.     return;
  3052.   }
  3053.  
  3054.   textWin << "The index file checks good." << "\n";
  3055. }
  3056.  
  3057. void RebuildIndexFile(MyTextWindow &textWin)
  3058. {
  3059.   textWin.Clear();
  3060.   textWin << "Rebuilding the index file..." << "\n";
  3061.   UString sbuf;
  3062.   
  3063.   char *FileName = wxFileSelector("Enter name for new index file:",
  3064.                   NULL, NULL, NULL, "*.*");
  3065.   if(FileName) {
  3066. #ifdef wx_msw
  3067.     wxUnix2DosFilename(FileName);
  3068. #endif
  3069.   }
  3070.   else {
  3071.     textWin << "Rebuild canceled." << "\n";
  3072.     return; // No vaild file name
  3073.   }
  3074.  
  3075.   if(VBDFile::Exists(FileName)) {
  3076.     sbuf = sbuf + "The " + FileName + " file already exists!\nOverwrite it?";
  3077.     int yn = wxMessageBox(sbuf.c_str(), "File Exists", wxYES_NO|wxCENTRE);
  3078.  
  3079.     if(yn == wxNO) {
  3080.     textWin << "Rebuild canceled." << "\n";
  3081.     return;
  3082.     }
  3083.  
  3084.     if(!wxRemoveFile(FileName)) {
  3085.       sbuf.DeleteAt(0, sbuf.length());
  3086.       sbuf = sbuf + "Could not write to: " + FileName;
  3087.       textWin << sbuf.c_str() << "\n";
  3088.       Error->Message(sbuf.c_str());
  3089.       return; 
  3090.     }
  3091.   }
  3092.   
  3093.   StrDB strdb(DB);
  3094.   int rv = strdb.RebuildIndexFile(FileName);
  3095.   
  3096.   if(!rv) {
  3097.     textWin << "The index file was not rebuilt!" << "\n";
  3098.     return;
  3099.   }
  3100.  
  3101.   textWin << "The index file was rebuilt." << "\n";
  3102.   textWin << "A new index file named:\n"
  3103.       << FileName << " was created." << "\n";
  3104. }
  3105.  
  3106. int PrintPSItemBar(ofstream &stream, PostScriptDrv &psdrv,
  3107.             int x_offset, int char_offset, int cell_len)
  3108. {
  3109.   if(KeyName != 0) {
  3110.     psdrv.PrintLine((char *)KeyName, cell_len, stream);
  3111.     x_offset += char_offset;
  3112.   } 
  3113.   if(M2Name != 0) {
  3114.     psdrv.MoveTo(stream, x_offset, psdrv.row);
  3115.     psdrv.PrintLine((char *)M2Name, cell_len, stream);
  3116.     x_offset += char_offset;
  3117.   }
  3118.   
  3119.   if(M3Name != 0) {
  3120.     psdrv.MoveTo(stream, x_offset, psdrv.row);
  3121.     psdrv.PrintLine((char *)M3Name, cell_len, stream);
  3122.     x_offset += char_offset;
  3123.   }
  3124.  
  3125.   if(M4Name != 0) {
  3126.     psdrv.MoveTo(stream, x_offset, psdrv.row);
  3127.     psdrv.PrintLine((char *)M4Name, cell_len, stream);
  3128.     x_offset += char_offset;
  3129.   }
  3130.  
  3131.   if(M5Name != 0) {
  3132.     psdrv.MoveTo(stream, x_offset, psdrv.row);
  3133.     psdrv.PrintLine((char *)M5Name, cell_len, stream);
  3134.     x_offset += char_offset;
  3135.   }
  3136.  
  3137.   if(M6Name != 0) {
  3138.     psdrv.MoveTo(stream, x_offset, psdrv.row);
  3139.     psdrv.PrintLine((char *)M6Name, cell_len, stream);
  3140.     x_offset += char_offset;
  3141.   }
  3142.  
  3143.   if(M7Name != 0) {
  3144.     psdrv.MoveTo(stream, x_offset, psdrv.row);
  3145.     psdrv.PrintLine((char *)M7Name, cell_len, stream);
  3146.     x_offset += char_offset;
  3147.   }
  3148.  
  3149.   if(M8Name != 0) {
  3150.     psdrv.MoveTo(stream, x_offset, psdrv.row);
  3151.     psdrv.PrintLine((char *)M8Name, cell_len, stream);
  3152.     x_offset += char_offset;
  3153.   }
  3154.  
  3155.   if(Comments != 0) {
  3156.     psdrv.MoveTo(stream, x_offset, psdrv.row);
  3157.     psdrv.PrintLine((char *)Comments, cell_len, stream);
  3158.     x_offset += char_offset;
  3159.   }
  3160.   return x_offset;
  3161. }
  3162.  
  3163. void PostScriptPrint(MyTextWindow &textWin)
  3164. {
  3165.   textWin.Clear();
  3166.   textWin << "Printing database to PostScript file..." << "\n";
  3167.   int yn, i;
  3168.   
  3169.   if(DB->RebuildIndex()) {
  3170.     textWin << "\n";
  3171.     textWin << "The index file needs to be rebuilt." << "\n";
  3172.     return;
  3173.   }
  3174.  
  3175.   // Setup the default values for user configurable PostScript parameters
  3176.   int cell_len = 19;    
  3177.   double font_size = 7; 
  3178.   int orientation = 1;
  3179.   const int DocNameLen = 255;
  3180.   char psDocName[DocNameLen];
  3181.   for(i = 0; i < DocNameLen; i++) psDocName[i] = 0;
  3182.   strcpy(psDocName, ProgramName);
  3183.  
  3184.   PostScriptDrv::PSPaperSizes paper_code = PostScriptDrv::LETTER_SIZE;
  3185.   PostScriptDrv::PSFonts item_font = PostScriptDrv::COURIER_BOLD_OBLIQUE;
  3186.   PostScriptDrv::PSFonts cell_font = PostScriptDrv::COURIER;
  3187.  
  3188.   // Load the PostScript configuration from the config file
  3189.   char *CurrentCfgFile;
  3190.   char *CfgFile;
  3191.   Config *CfgData = new Config;
  3192.  
  3193.   // Look for CfgFile name in environment
  3194.   if((CurrentCfgFile = getenv(EnvSetting)) == 0)
  3195.     CfgFile = (char *)DefaultCfgFile;
  3196.   else
  3197.     CfgFile = CurrentCfgFile;
  3198.  
  3199.   int FileStatus = CfgData->Load((char *)CfgFile);
  3200.   if(FileStatus) { // Found a valid config file
  3201. // *********************************************************** //
  3202. // Add all PostScript config file entries here
  3203. // *********************************************************** //
  3204.     int int_val = 0;
  3205.     double dfp_val = 0;
  3206.     char *str_val = 0;
  3207.  
  3208.     int_val = CfgData->GetIntValue("CellLength");
  3209.     if(int_val > 0) cell_len = int_val;
  3210.  
  3211.     dfp_val = CfgData->GetDFPValue("FontSize");
  3212.     if(dfp_val > 0) font_size = dfp_val;
  3213.  
  3214.     str_val = CfgData->GetStrValue("Orientation");
  3215.     if(str_val != 0) {
  3216.       if(strcmp(str_val, "PORTRAIT") == 0) orientation = 0;
  3217.       str_val = 0;
  3218.     }
  3219.     
  3220.     str_val = CfgData->GetStrValue("PaperSize");
  3221.     if(str_val != 0) {
  3222.       if(strcmp(str_val, "LETTER") == 0)
  3223.     paper_code = PostScriptDrv::LETTER_SIZE;
  3224.       if(strcmp(str_val, "LEGAL") == 0)
  3225.     paper_code = PostScriptDrv::LEGAL_SIZE;
  3226.       if(strcmp(str_val, "TABLOID") == 0)
  3227.     paper_code = PostScriptDrv::TABLOID_SIZE;
  3228.       if(strcmp(str_val, "A3") == 0) paper_code = PostScriptDrv::A3_SIZE;
  3229.       if(strcmp(str_val, "A4") == 0) paper_code = PostScriptDrv::A4_SIZE;
  3230.       str_val = 0;
  3231.     }
  3232.  
  3233.     str_val = CfgData->GetStrValue("ItemBarFont");
  3234.     if(str_val != 0) {
  3235.       if(strcmp(str_val, "COURIER") == 0)
  3236.     item_font = PostScriptDrv::COURIER;
  3237.       if(strcmp(str_val, "COURIER_BOLD") == 0)
  3238.     item_font = PostScriptDrv::COURIER_BOLD;
  3239.       if(strcmp(str_val, "COURIER_OBLIQUE") == 0)
  3240.     item_font = PostScriptDrv::COURIER_OBLIQUE;
  3241.       if(strcmp(str_val, "COURIER_BOLD_OBLIQUE") == 0)
  3242.     item_font = PostScriptDrv::COURIER_BOLD_OBLIQUE;
  3243.       str_val = 0;
  3244.     }
  3245.     
  3246.     str_val = CfgData->GetStrValue("CellFont");
  3247.     if(str_val != 0) {
  3248.       if(strcmp(str_val, "COURIER") == 0)
  3249.     cell_font = PostScriptDrv::COURIER;
  3250.       if(strcmp(str_val, "COURIER_BOLD") == 0)
  3251.     cell_font = PostScriptDrv::COURIER_BOLD;
  3252.       if(strcmp(str_val, "COURIER_OBLIQUE") == 0)
  3253.     cell_font = PostScriptDrv::COURIER_OBLIQUE;
  3254.       if(strcmp(str_val, "COURIER_BOLD_OBLIQUE") == 0)
  3255.     cell_font = PostScriptDrv::COURIER_BOLD_OBLIQUE;
  3256.     }
  3257.     
  3258.     str_val = CfgData->GetStrValue("psDocumentName");
  3259.     if(str_val != 0) {
  3260.       for(i = 0; i < DocNameLen; i++) psDocName[i] = 0;
  3261.       strcpy(psDocName, str_val);
  3262.     }
  3263. // *********************************************************** //    
  3264.   }
  3265.   CfgData->UnLoad(); // Unload the Config file from memory
  3266.  
  3267.   if(displaying_list) {
  3268.     yn = wxMessageBox("Print display list objects?",
  3269.             "Program Message", wxYES_NO|wxCENTRE);
  3270.   }
  3271.   else {
  3272.     yn = wxNO;
  3273.   }
  3274.   
  3275.   if(yn == wxNO) LoadIndexKeys();
  3276.   if(dllist->IsEmpty()) LoadIndexKeys();
  3277.     
  3278.   char *FileName = wxFileSelector("Print database to PostScript file:",
  3279.                   NULL, NULL, NULL, "*.*");
  3280.   if(FileName) {
  3281. #ifdef wx_msw
  3282.     wxUnix2DosFilename(FileName);
  3283. #endif
  3284.   }
  3285.   else {
  3286.     textWin << "PostScript print canceled." << "\n";
  3287.     return; // No vaild file name
  3288.   }
  3289.   
  3290.   UString sbuf;
  3291.   if(VBDFile::Exists(FileName)) {
  3292.     sbuf = sbuf + "The " + FileName + " file already exists!\nOverwrite it?";
  3293.     yn = wxMessageBox(sbuf.c_str(), "File Exists", wxYES_NO|wxCENTRE);
  3294.  
  3295.     if(yn == wxNO) {
  3296.       textWin << "PostScript print canceled." << "\n";
  3297.       return;
  3298.     }
  3299.   }
  3300.   
  3301.   ofstream stream(FileName, ios::out); // Open file and truncate it
  3302.   textWin << "Printing to: " << FileName << "\n";
  3303.   
  3304.   if(!stream) { // Could not open the stream
  3305.     sbuf.DeleteAt(0, sbuf.length());
  3306.     sbuf = sbuf + "Could not write to: " + FileName;
  3307.     textWin << sbuf.c_str() << "\n";
  3308.     Error->Message(sbuf.c_str());
  3309.     return; 
  3310.   }
  3311.  
  3312.   PostScriptDrv psdrv;
  3313.   psdrv.Copies(1);
  3314.  
  3315.   // Setup the PostScript driver
  3316.   psdrv.SetPaperSize(paper_code);
  3317.   psdrv.SetFont(cell_font, font_size);
  3318.   psdrv.UseHeader();
  3319.   if(orientation == 1) psdrv.LandScapeMode();
  3320.   psdrv.SetDocumentName(psDocName);
  3321.   char time_buf[255]; // Buffer used to hold time/date string
  3322.   GetSystemTime(time_buf);
  3323.   psdrv.SetDateString(time_buf);
  3324.   psdrv.DocumentSetup();
  3325.   psdrv.Prologue(stream);
  3326.   psdrv.MediaSetup(stream);
  3327.   StrDB strdb(DB);
  3328.   int char_offset = int((cell_len + 1) * psdrv.CharWidth());
  3329.   int x_offset;
  3330.   if(orientation == 0)
  3331.     x_offset = int(HEADER_OFFSET * PIXELS_PER_INCH);
  3332.   else
  3333.     x_offset = PRINTABLE_OFFSET_X;
  3334.  
  3335.   int lines = 4;
  3336.   psdrv.StartPage(psdrv.page_count + 1, stream);
  3337.   psdrv.row = psdrv.StartY();
  3338.   psdrv.MoveTo(stream, psdrv.StartX(), psdrv.row);
  3339.  
  3340.   psdrv.ChangeFont(stream, item_font, font_size);
  3341.   x_offset = PrintPSItemBar(stream, psdrv, x_offset, char_offset, cell_len);
  3342.   psdrv.ChangeFont(stream, cell_font, font_size);
  3343.   
  3344.   int line_points;
  3345.   if(orientation == 0)
  3346.     line_points = int(x_offset - (HEADER_OFFSET * PIXELS_PER_INCH));
  3347.   else
  3348.     line_points = x_offset - PRINTABLE_OFFSET_X;
  3349.  
  3350.   psdrv.row -= (int)psdrv.FontSize();
  3351.   lines++;
  3352.   psdrv.drawThickLine(stream, line_points, psdrv.StartX(), psdrv.row);
  3353.   psdrv.row -= THICK_LINE_WIDTH + psdrv.FontSize();
  3354.   lines ++;
  3355.  
  3356.   dllistptr = dllist->GetFront();
  3357.   textWin << "Printing..." << "\n";
  3358.   while(!dllist->IsHeader(dllistptr)) {
  3359.     strdb.ReadObject(dllistptr->Data.object_address);
  3360.     if(orientation == 0)
  3361.       x_offset = int(HEADER_OFFSET * PIXELS_PER_INCH);
  3362.     else
  3363.       x_offset = PRINTABLE_OFFSET_X;
  3364.  
  3365.     if(KeyName != 0) {
  3366.       psdrv.MoveTo(stream, x_offset, psdrv.row);
  3367.       psdrv.PrintLine(strdb.GetKM(), cell_len, stream);
  3368.       x_offset += char_offset;
  3369.     } 
  3370.     if(M2Name != 0) {
  3371.       psdrv.MoveTo(stream, x_offset, psdrv.row);
  3372.       psdrv.PrintLine(strdb.GetM2(), cell_len, stream);
  3373.       x_offset += char_offset;
  3374.     }
  3375.     
  3376.     if(M3Name != 0) {
  3377.       psdrv.MoveTo(stream, x_offset, psdrv.row);
  3378.       psdrv.PrintLine(strdb.GetM3(), cell_len, stream);
  3379.       x_offset += char_offset;
  3380.     }
  3381.     
  3382.     if(M4Name != 0) {
  3383.       psdrv.MoveTo(stream, x_offset, psdrv.row);
  3384.       psdrv.PrintLine(strdb.GetM4(), cell_len, stream);
  3385.     x_offset += char_offset;
  3386.     }
  3387.     
  3388.     if(M5Name != 0) {
  3389.       psdrv.MoveTo(stream, x_offset, psdrv.row);
  3390.       psdrv.PrintLine(strdb.GetM5(), cell_len, stream);
  3391.       x_offset += char_offset;
  3392.     }
  3393.     
  3394.     if(M6Name != 0) {
  3395.       psdrv.MoveTo(stream, x_offset, psdrv.row);
  3396.       psdrv.PrintLine(strdb.GetM6(), cell_len, stream);
  3397.       x_offset += char_offset;
  3398.     }
  3399.     
  3400.     if(M7Name != 0) {
  3401.       psdrv.MoveTo(stream, x_offset, psdrv.row);
  3402.       psdrv.PrintLine(strdb.GetM7(), cell_len, stream);
  3403.       x_offset += char_offset;
  3404.     }
  3405.     
  3406.     if(M8Name != 0) {
  3407.       psdrv.MoveTo(stream, x_offset, psdrv.row);
  3408.       psdrv.PrintLine(strdb.GetM8(), cell_len, stream);
  3409.       x_offset += char_offset;
  3410.     }
  3411.     
  3412.     if(Comments != 0) {
  3413.       psdrv.MoveTo(stream, x_offset, psdrv.row);
  3414.       psdrv.PrintLine(strdb.GetCM(), cell_len, stream);
  3415.       x_offset += char_offset;
  3416.     }
  3417.     psdrv.row -= psdrv.FontSize();
  3418.     lines++;
  3419.     if(orientation == 0)
  3420.       line_points = int(x_offset - (HEADER_OFFSET * PIXELS_PER_INCH));
  3421.     else
  3422.       line_points = x_offset - PRINTABLE_OFFSET_X;
  3423.     psdrv.drawLine(stream, line_points, psdrv.StartX(), psdrv.row);
  3424.     psdrv.row -= LINE_WIDTH + psdrv.FontSize();
  3425.     lines++; // Increment the line count
  3426.  
  3427.     if(lines >= psdrv.LinesPerPage()) {
  3428.       psdrv.EndPage(stream);
  3429.       psdrv.StartPage(psdrv.page_count + 1, stream);
  3430.       if(orientation == 0)
  3431.     x_offset = int(HEADER_OFFSET * PIXELS_PER_INCH);
  3432.       else
  3433.     x_offset = PRINTABLE_OFFSET_X;
  3434.       psdrv.row = psdrv.StartY();
  3435.       lines = 4;
  3436.       psdrv.MoveTo(stream, psdrv.StartX(), psdrv.row);
  3437.       psdrv.ChangeFont(stream, item_font, font_size);
  3438.       x_offset = PrintPSItemBar(stream, psdrv, x_offset,
  3439.                 char_offset, cell_len);
  3440.       psdrv.ChangeFont(stream, cell_font, font_size);
  3441.       if(orientation == 0)
  3442.     line_points = int(x_offset - (HEADER_OFFSET * PIXELS_PER_INCH));
  3443.       else
  3444.     line_points = x_offset - PRINTABLE_OFFSET_X;
  3445.       psdrv.row -= (int)psdrv.FontSize();
  3446.       lines++;
  3447.       psdrv.drawThickLine(stream, line_points, psdrv.StartX(), psdrv.row);
  3448.       psdrv.row -= THICK_LINE_WIDTH + psdrv.FontSize();
  3449.       lines ++;
  3450.     }
  3451.     dllistptr = dllistptr->GetNext();
  3452.   }
  3453.   psdrv.EndPage(stream);
  3454.   psdrv.Epilogue(stream, psdrv.page_count);
  3455.   
  3456.   textWin << "Finished." << "\n";
  3457.   stream.close();
  3458. }
  3459.  
  3460. #ifdef __USE_MSW_PRINTING__
  3461.  
  3462. void  page_btn_proc(wxButton& but, wxCommandEvent& event)
  3463. // Button procedures for the MSW Page Setup Dialog box
  3464. {
  3465.   long tag = (long)but.GetClientData() ;
  3466.  
  3467.   if(tag == PAGE_DIALOG_BUTTON_CLOSE) {
  3468.     wxPageDialog->Show(FALSE);
  3469.     delete wxPageDialog;
  3470.   }
  3471.  
  3472.   if(tag == PAGE_DIALOG_BUTTON_ACCEPT) {
  3473.     MSWPrintSetup->lines_per_page = LppSlider->GetValue();
  3474.     MSWPrintSetup->cell_length = CellSlider->GetValue();
  3475.     MSWPrintSetup->font_size = FsSlider->GetValue();
  3476.     MSWPrintSetup->orientation = OrientationChoice->GetSelection();
  3477.     MSWPrintSetup->font = FontChoice->GetSelection();
  3478.     MSWPrintSetup->lr_margin = LRMSlider->GetValue();
  3479.     
  3480.     MSWPrintSetup->prev_lines_per_page = LppSlider->GetValue();
  3481.     MSWPrintSetup->prev_cell_length = CellSlider->GetValue();
  3482.     MSWPrintSetup->prev_font_size = FsSlider->GetValue();
  3483.     MSWPrintSetup->prev_orientation = OrientationChoice->GetSelection();
  3484.     MSWPrintSetup->prev_font = FontChoice->GetSelection();
  3485.     MSWPrintSetup->prev_lr_margin = LRMSlider->GetValue();
  3486.   }
  3487.  
  3488.   if(tag == PAGE_DIALOG_BUTTON_CANCEL) {
  3489.     LppSlider->SetValue(MSWPrintSetup->prev_lines_per_page);
  3490.     CellSlider->SetValue(MSWPrintSetup->prev_cell_length);
  3491.     FsSlider->SetValue(MSWPrintSetup->prev_font_size);
  3492.     OrientationChoice->SetSelection(MSWPrintSetup->prev_orientation);
  3493.     FontChoice->SetSelection(MSWPrintSetup->prev_font);
  3494.     LRMSlider->SetValue(MSWPrintSetup->prev_lr_margin);
  3495.   }
  3496.  
  3497.   if(tag == PAGE_DIALOG_BUTTON_DEFAULT) {
  3498.     LppSlider->SetValue(MSWPrintSetup->default_lines_per_page);
  3499.     CellSlider->SetValue(MSWPrintSetup->default_cell_length);
  3500.     FsSlider->SetValue(MSWPrintSetup->default_font_size);
  3501.     OrientationChoice->SetSelection(MSWPrintSetup->default_orientation);
  3502.     FontChoice->SetSelection(MSWPrintSetup->default_font);
  3503.     LRMSlider->SetValue(MSWPrintSetup->default_lr_margin);
  3504.   }
  3505. }
  3506.  
  3507. void wStrDBPrint::SetFont(int style, int weight)
  3508. {
  3509.   switch(MSWPrintSetup->font) {
  3510.     case 0:
  3511.       printerFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3512.                             wxSWISS, style, weight);
  3513.       char_width = .6 * MSWPrintSetup->font_size;
  3514.       break;
  3515.  
  3516.     case 1:
  3517.       printerFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3518.                             wxROMAN, style, weight);
  3519.       char_width = .6 * MSWPrintSetup->font_size;
  3520.       break;
  3521.  
  3522.     case 2:
  3523.       printerFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3524.                             wxDECORATIVE,
  3525.                             style, weight);
  3526.       char_width = .6 * MSWPrintSetup->font_size;
  3527.       break;
  3528.  
  3529.     case 3:
  3530.       printerFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3531.                             wxMODERN, style, weight);
  3532.       char_width = .6 * MSWPrintSetup->font_size;
  3533.       break;
  3534.     
  3535.     case 4:
  3536.       printerFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3537.                             wxSCRIPT, style, weight);
  3538.       char_width = .6 * MSWPrintSetup->font_size;
  3539.       break;
  3540.  
  3541.     case 5:
  3542.       printerFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3543.                             wxDEFAULT, style, weight);
  3544.       char_width = .6 * MSWPrintSetup->font_size;
  3545.       break;
  3546.  
  3547.     default:
  3548.       printerFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3549.                             wxSWISS, style, weight);
  3550.       char_width = .6 * MSWPrintSetup->font_size;
  3551.       break;
  3552.   };
  3553. }
  3554.  
  3555. void wStrDBPrint::SetItemBarFont(int style, int weight)
  3556. {
  3557.   switch(MSWPrintSetup->font) {
  3558.     case 0:
  3559.       itembarFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3560.                             wxSWISS, style, weight);
  3561.       break;
  3562.  
  3563.     case 1:
  3564.       itembarFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3565.                             wxROMAN, style, weight);
  3566.       break;
  3567.  
  3568.     case 2:
  3569.       itembarFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3570.                             wxDECORATIVE,
  3571.                             style, weight);
  3572.       break;
  3573.  
  3574.     case 3:
  3575.       itembarFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3576.                             wxMODERN, style, weight);
  3577.       break;
  3578.     
  3579.     case 4:
  3580.       itembarFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3581.                             wxSCRIPT, style, weight);
  3582.       break;
  3583.  
  3584.     case 5:
  3585.       itembarFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3586.                             wxDEFAULT, style, weight);
  3587.       break;
  3588.  
  3589.     default:
  3590.       itembarFont = wxTheFontList->FindOrCreateFont(MSWPrintSetup->font_size,
  3591.                             wxSWISS, style, weight);
  3592.       break;
  3593.   };
  3594. }
  3595.  
  3596. void wStrDBPrint::OnPreparePrinting()
  3597. // Called once by the framework before any other demands are made
  3598. // of the wxPrintout object. 
  3599. {
  3600.   SetFont();
  3601.   SetItemBarFont();
  3602.   SetHeaderFont(15, wxSWISS, wxNORMAL, wxBOLD);
  3603. }
  3604.  
  3605. Bool wStrDBPrint::OnPrintPage(int page)
  3606. // Called by the framework when a page should be printed.
  3607. // Returning FALSE cancels the print job. The application
  3608. // can use wxPrintout::GetDC to obtain a device context to
  3609. // draw on.
  3610. {
  3611.   wxDC *dc = GetDC();
  3612.   if(dc) {
  3613.       DrawTextPage(dc, page);
  3614.     return TRUE;
  3615.   }
  3616.   else
  3617.     return FALSE;
  3618. }
  3619.  
  3620. Bool wStrDBPrint::OnBeginDocument(int startPage, int endPage)
  3621. // Called by the framework at the start of document printing.
  3622. // OnBeginDocument is called once for every copy printed. 
  3623. // The base wxPrintout::OnBeginDocument must be called
  3624. // (and the return value checked) from within the overriden
  3625. // function, since it calls wxDC::StartDoc.
  3626. {
  3627.   if (!wxPrintout::OnBeginDocument(startPage, endPage))
  3628.     return FALSE; // Returns FALSE if the print job is canceled
  3629.  
  3630.   return TRUE;
  3631. }
  3632.  
  3633. Bool wStrDBPrint::HasPage(int pageNum)
  3634. // Should be overriden to return TRUE if the document has this page,
  3635. // or FALSE if not. Returning FALSE signifies the end of the document.
  3636. // By default, HasPage behaves as if the document has only one page.
  3637. {
  3638.   // Calculate the number of pages in this document
  3639.   int minPage, maxPage, selPageFrom, selPageTo;
  3640.   GetPageInfo(&minPage, &maxPage, &selPageFrom, &selPageTo);
  3641.   return (pageNum == minPage) || (pageNum <= maxPage);
  3642. }
  3643.  
  3644. void wStrDBPrint::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom,
  3645.                   int *selPageTo)
  3646. // Called by the framework to obtain information from the application
  3647. // about minimum and maximum page values that the user can select, and
  3648. // the required page range to be printed.
  3649. {
  3650.   if(DB->RebuildIndex()) { // The index files needs to be rebuilt
  3651.     *minPage = 1;
  3652.     *selPageFrom = 1;
  3653.     *selPageTo = 1;
  3654.     *maxPage = 1;
  3655.     return;
  3656.   }
  3657.  
  3658.   StrDB strdb(DB);
  3659.   if(print_list == 0) num_objects = LoadIndexKeys();
  3660.   if(dllist->IsEmpty()) num_objects = LoadIndexKeys();
  3661.   dllistptr = dllist->GetFront();
  3662.  
  3663.   int lines = num_objects; 
  3664.   int first_page = 1; // Always starting on page one
  3665.   int last_page = 1;  // Default is the first page
  3666.   
  3667.   *minPage = first_page;     // Always starting on page one
  3668.   *selPageFrom = first_page; // Always starting on page one
  3669.  
  3670.   for(;;) {
  3671.     if(lines <= MSWPrintSetup->lines_per_page) break;
  3672.     lines = lines - MSWPrintSetup->lines_per_page;
  3673.     last_page++; // Increment the page count
  3674.   }
  3675.   
  3676.   *selPageTo = last_page;
  3677.   *maxPage = last_page;
  3678. }
  3679.  
  3680. void wStrDBPrint::ScaleDC(wxDC *dc)
  3681. // Scale the DC so that the printout roughly represents the
  3682. // the screen scaling.
  3683. {
  3684.   // Get the page size 
  3685.   GetPageSizeMM(&page_width, &page_height);
  3686.   
  3687.     // Get the logical pixels per inch of screen and printer
  3688.   GetPPIScreen(&ppiScreenX, &ppiScreenY);
  3689.   GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
  3690.  
  3691.   // Scale the DC so that the printout roughly represents the
  3692.   // the screen scaling.
  3693.   scale = (float)((float)ppiPrinterX/(float)ppiScreenX);
  3694.  
  3695.   // Calculate conversion factor for converting millimetres into
  3696.   // logical units. There are approx. 25.1 mm to the inch. There
  3697.   // are ppi device units to the inch. Therefore 1 mm corresponds
  3698.   // to ppi/25.1 device units.
  3699.   logUnitsFactor = (float)(ppiPrinterX / (scale * 25.1));
  3700.  
  3701.   // Check real page size in case it is reduced by print preview 
  3702.   int pageWidth, pageHeight;
  3703.   float w, h;
  3704.   dc->GetSize(&w, &h);
  3705.   GetPageSizePixels(&pageWidth, &pageHeight);
  3706.   
  3707.   // Do not change if printer pageWidth == current DC width
  3708.   float overallScale = scale * (float)(w/(float)pageWidth);
  3709.   dc->SetUserScale(overallScale, overallScale);
  3710. }
  3711.  
  3712. void wStrDBPrint::DrawTextPage(wxDC *dc, int page)
  3713. // Write page by page with margins, header, and page numbers
  3714. {
  3715.   dc->SetFont(itembarFont); // Set the text font for the item bar
  3716.   ScaleDC(dc);
  3717.   
  3718.   start_x = (float)(logUnitsFactor * MSWPrintSetup->lr_margin);
  3719.   start_y = (float)(logUnitsFactor * MSWPrintSetup->tb_margin);
  3720.  
  3721.   int end = page * MSWPrintSetup->lines_per_page;  // Last line to write
  3722.   int start = end - MSWPrintSetup->lines_per_page; // First line to write
  3723.  
  3724.   float textW, textH; // Text width and height 
  3725.   float xpos = start_x; 
  3726.   float ypos = start_y;
  3727.  
  3728.   int char_offset = int((MSWPrintSetup->cell_length + 1) * char_width);
  3729.   float x_offset = xpos;
  3730.  
  3731.   if(KeyName != 0) {
  3732.     PrintText(dc, (char *)KeyName, MSWPrintSetup->cell_length,
  3733.           x_offset, ypos); 
  3734.     x_offset += char_offset;
  3735.     dc->GetTextExtent((char *)KeyName, &textW, &textH);
  3736.   } 
  3737.   if(M2Name != 0) {
  3738.     PrintText(dc, (char *)M2Name, MSWPrintSetup->cell_length, x_offset, ypos); 
  3739.     x_offset += char_offset;
  3740.   }
  3741.   
  3742.   if(M3Name != 0) {
  3743.     PrintText(dc, (char *)M3Name, MSWPrintSetup->cell_length, x_offset, ypos); 
  3744.     x_offset += char_offset;
  3745.   }
  3746.  
  3747.   if(M4Name != 0) {
  3748.     PrintText(dc, (char *)M4Name, MSWPrintSetup->cell_length, x_offset, ypos); 
  3749.     x_offset += char_offset;
  3750.   }
  3751.  
  3752.   if(M5Name != 0) {
  3753.     PrintText(dc, (char *)M5Name, MSWPrintSetup->cell_length, x_offset, ypos); 
  3754.     x_offset += char_offset;
  3755.   }
  3756.  
  3757.   if(M6Name != 0) {
  3758.     PrintText(dc, (char *)M6Name, MSWPrintSetup->cell_length, x_offset, ypos); 
  3759.     x_offset += char_offset;
  3760.   }
  3761.  
  3762.   if(M7Name != 0) {
  3763.     PrintText(dc, (char *)M7Name, MSWPrintSetup->cell_length, x_offset, ypos); 
  3764.     x_offset += char_offset;
  3765.   }
  3766.  
  3767.   if(M8Name != 0) {
  3768.     PrintText(dc, (char *)M8Name, MSWPrintSetup->cell_length, x_offset, ypos); 
  3769.     x_offset += char_offset;
  3770.   }
  3771.  
  3772.   if(Comments != 0) {
  3773.     PrintText(dc, (char *)Comments, MSWPrintSetup->cell_length,
  3774.           x_offset, ypos); 
  3775.     x_offset += char_offset;
  3776.   }
  3777.  
  3778.   ypos += textH;
  3779.   dc->DrawLine(xpos , ypos, x_offset, ypos);
  3780.   ypos += mswpLINE_WIDTH;
  3781.  
  3782.   int lines = 0;
  3783.   StrDB strdb(DB);
  3784.   dc->SetFont(printerFont); // Set the text font for the objects
  3785.   
  3786.   for(int i = 0; i < start; i++) {
  3787.     if(!dllist->IsHeader(dllistptr)) 
  3788.       dllistptr = dllistptr->GetNext();
  3789.   }
  3790.  
  3791.   while(!dllist->IsHeader(dllistptr)) {
  3792.     strdb.ReadObject(dllistptr->Data.object_address);
  3793.     x_offset = xpos;
  3794.     ypos += mswpLINE_WIDTH;
  3795.     if(KeyName != 0) {
  3796.       PrintText(dc, strdb.GetKM(), MSWPrintSetup->cell_length,
  3797.         x_offset, ypos); 
  3798.       x_offset += char_offset;
  3799.       dc->GetTextExtent(strdb.GetKM(), &textW, &textH);
  3800.     } 
  3801.     if(M2Name != 0) {
  3802.       PrintText(dc, strdb.GetM2(), MSWPrintSetup->cell_length,
  3803.         x_offset, ypos); 
  3804.       x_offset += char_offset;
  3805.     }
  3806.     
  3807.     if(M3Name != 0) {
  3808.       PrintText(dc, strdb.GetM3(), MSWPrintSetup->cell_length,
  3809.         x_offset, ypos); 
  3810.       x_offset += char_offset;
  3811.     }
  3812.     
  3813.     if(M4Name != 0) {
  3814.       PrintText(dc, strdb.GetM4(), MSWPrintSetup->cell_length,
  3815.         x_offset, ypos); 
  3816.       x_offset += char_offset;
  3817.     }
  3818.     
  3819.     if(M5Name != 0) {
  3820.       PrintText(dc, strdb.GetM5(), MSWPrintSetup->cell_length,
  3821.         x_offset, ypos); 
  3822.       x_offset += char_offset;
  3823.     }
  3824.     
  3825.     if(M6Name != 0) {
  3826.       PrintText(dc, strdb.GetM6(), MSWPrintSetup->cell_length,
  3827.         x_offset, ypos); 
  3828.       x_offset += char_offset;
  3829.     }
  3830.     
  3831.     if(M7Name != 0) {
  3832.       PrintText(dc, strdb.GetM7(), MSWPrintSetup->cell_length,
  3833.         x_offset, ypos); 
  3834.       x_offset += char_offset;
  3835.     }
  3836.     
  3837.     if(M8Name != 0) {
  3838.       PrintText(dc, strdb.GetM8(), MSWPrintSetup->cell_length,
  3839.         x_offset, ypos); 
  3840.       x_offset += char_offset;
  3841.     }
  3842.     
  3843.     if(Comments != 0) {
  3844.       PrintText(dc, strdb.GetCM(), MSWPrintSetup->cell_length,
  3845.         x_offset, ypos); 
  3846.       x_offset += char_offset;
  3847.     }
  3848.     ypos += textH;
  3849.     ypos += mswpLINE_WIDTH;
  3850.     dc->DrawLine(xpos , ypos, x_offset, ypos);
  3851.     ypos += mswpLINE_WIDTH;
  3852.     lines++;
  3853.     if(lines >= MSWPrintSetup->lines_per_page) break;
  3854.     dllistptr = dllistptr->GetNext();
  3855.   }
  3856.   
  3857.  
  3858.   char time_buf[255];      // Buffer used to hold time/date string
  3859.   GetSystemTime(time_buf); // Part of the PostScript Driver class
  3860.   WritePageHeader(dc, mswpDocumentName, time_buf);
  3861.   WritePageNumber(dc, page);
  3862. }
  3863.  
  3864. void wStrDBPrint::SetHeaderFont(int size, int font, int style, int weight)
  3865. // Set the header and page number font type, size, and style
  3866. {
  3867.   headerFont = wxTheFontList->FindOrCreateFont(size, font, style, weight);
  3868. }
  3869.  
  3870. void wStrDBPrint::WritePageHeader(wxDC *dc, char *doc_name, char *doc_date)
  3871. // Writes header on top of page. Margin units are in millimetres.
  3872. {
  3873.   dc->SetFont(headerFont);
  3874.  
  3875.   // Offset the margins to move text above the first line
  3876.   int leftMargin  = MSWPrintSetup->lr_margin / 2;
  3877.   int topMargin   = MSWPrintSetup->tb_margin / 2;
  3878.   int rightMargin = MSWPrintSetup->lr_margin / 2;
  3879.  
  3880.   float leftMarginLogical = (float)(logUnitsFactor * leftMargin);
  3881.   float topMarginLogical = (float)(logUnitsFactor * topMargin);
  3882.   float rightMarginLogical = (float)(logUnitsFactor* \
  3883.                      (page_width - rightMargin));
  3884.  
  3885.   float xExtentName, yExtentName, xExtentDate, yExtentDate, xPos, offset;
  3886.   dc->GetTextExtent(doc_name, &xExtentName, &yExtentName);
  3887.   if(doc_date != 0) { // Printing document name and date strings
  3888.     dc->GetTextExtent(doc_date, &xExtentDate, &yExtentDate);
  3889.  
  3890.     // Draw the document's name left justified
  3891.     PrintText(dc, doc_name, start_x, topMarginLogical);
  3892.  
  3893.     // Draw the document's date right justified
  3894.     if(MSWPrintSetup->orientation == 0) // Landscape printing
  3895.       offset = (logUnitsFactor * page_width) - \
  3896.        (logUnitsFactor * (MSWPrintSetup->lr_margin + mswpPRINTABLE_OFFSET_X));
  3897.     else
  3898.       offset = (logUnitsFactor * page_width) - \
  3899.     (logUnitsFactor * MSWPrintSetup->lr_margin);
  3900.       
  3901.     xPos = (float)(offset - xExtentDate);
  3902.     PrintText(dc, doc_date, xPos, topMarginLogical);
  3903.   }
  3904.   else { // Center the document's name
  3905.     xPos = (float)(((((page_width - leftMargin - rightMargin)/2.0)
  3906.              +leftMargin)*logUnitsFactor) - (xExtentName/2.0));
  3907.     PrintText(dc, doc_name, xPos, topMarginLogical);
  3908.   }
  3909. }
  3910.  
  3911. void wStrDBPrint::WritePageNumber(wxDC *dc, int pagenum)
  3912. // Writes page number on bottom of page. Margin units are in millimetres.
  3913. {
  3914.   dc->SetFont(headerFont);
  3915.  
  3916.   // Offset the margins to move text below the last line
  3917.   int leftMargin = MSWPrintSetup->lr_margin;
  3918.   int bottomMargin = MSWPrintSetup->tb_margin;
  3919.   int rightMargin = MSWPrintSetup->lr_margin;
  3920.  
  3921.   float leftMarginLogical = (float)(logUnitsFactor * leftMargin);
  3922.  
  3923.   float bottomMarginLogical = (float)(logUnitsFactor * (page_height - \
  3924.                             bottomMargin));
  3925.  
  3926.   float rightMarginLogical = (float)(logUnitsFactor*(page_width - \
  3927.                              rightMargin));
  3928.   float xExtent, yExtent;
  3929.   char buf[255];
  3930.   sprintf(buf, "PAGE %d", pagenum);
  3931.   dc->GetTextExtent(buf, &xExtent, &yExtent);
  3932.   float xPos = (float)(((((page_width - leftMargin - rightMargin)/2.0)
  3933.              +leftMargin)*logUnitsFactor) - (xExtent/2.0));
  3934.   PrintText(dc, buf, xPos, bottomMarginLogical);
  3935. }
  3936.  
  3937. void wStrDBPrint::PrintText(wxDC *dc, char *s, int max_len,
  3938.                 float xpos, float ypos)
  3939. // Draw text in the device context.
  3940. {
  3941.   if(s == 0 || max_len <= 0) return;
  3942.  
  3943.   int slen = strlen(s);
  3944.   if(slen > max_len) {
  3945.     char *buf = new char[max_len];
  3946.     buf[max_len] = '\0';
  3947.     memmove(buf, s, max_len);
  3948.     dc->DrawText(buf, xpos, ypos);
  3949.     delete [] buf;
  3950.   }
  3951.   else
  3952.     dc->DrawText(s, xpos, ypos);
  3953. }
  3954.  
  3955. void wStrDBPrint::PrintText(wxDC *dc, char *s, float xpos, float ypos)
  3956. // Draw text in the device context.
  3957. {
  3958.   if(s == 0) return;
  3959.   dc->DrawText(s, xpos, ypos);
  3960. }
  3961.  
  3962. void wStrDBPrint::PrintText(wxDC *dc, char c, float xpos, float ypos)
  3963. {
  3964.   char s[1];
  3965.   s[0] = c;    // Copy char into a string buffer
  3966.   s[1] = '\0'; // Null terminate the string
  3967.   PrintText(dc, s, xpos, ypos);
  3968. }
  3969.  
  3970. void wStrDBPrint::PrintText(wxDC *dc, int i, float xpos, float ypos)
  3971. {
  3972.   char buf[255];
  3973.   sprintf(buf, "%d", i);
  3974.   PrintText(dc, buf, xpos, ypos);
  3975. }
  3976.  
  3977. void wStrDBPrint::PrintText(wxDC *dc, long i, float xpos, float ypos)
  3978. {
  3979.   char buf[255];
  3980.   sprintf(buf, "%d", i);
  3981.   PrintText(dc, buf, xpos, ypos);
  3982. }
  3983.  
  3984. void wStrDBPrint::PrintText(wxDC *dc, double i, float xpos, float ypos)
  3985. {
  3986.   char buf[255];
  3987.   sprintf(buf, "%.2f", i);
  3988.   PrintText(dc, buf, xpos, ypos);
  3989. }
  3990.  
  3991. void wStrDBPrint::PrintText(wxDC *dc, float i, float xpos, float ypos)
  3992. {
  3993.   char buf[255];
  3994.   sprintf(buf, "%.2f", i);
  3995.   PrintText(dc, buf, xpos, ypos);
  3996. }
  3997.  
  3998. #endif // __USE_MSW_PRINTING__
  3999.  
  4000. void HTMLPrint(MyTextWindow &textWin)
  4001. {
  4002.   textWin.Clear();
  4003.   textWin << "Printing database to an HTML file..." << "\n";
  4004.   int yn = 0;
  4005.   
  4006.   if(DB->RebuildIndex()) {
  4007.     textWin << "\n";
  4008.     textWin << "The index file needs to be rebuilt." << "\n";
  4009.     return;
  4010.   }
  4011.  
  4012.   if(displaying_list) {
  4013.     yn = wxMessageBox("Print display list objects?",
  4014.               "Program Message", wxYES_NO|wxCENTRE);
  4015.   }
  4016.   else {
  4017.     yn = wxNO;
  4018.   }
  4019.   
  4020.   if(yn == wxNO) LoadIndexKeys();
  4021.   if(dllist->IsEmpty()) LoadIndexKeys();
  4022.   
  4023.   char *FileName = wxFileSelector("Print database to file:",
  4024.                   NULL, NULL, NULL, "*.*");
  4025.   if(FileName) {
  4026. #ifdef wx_msw
  4027.     wxUnix2DosFilename(FileName);
  4028. #endif
  4029.   }
  4030.   else {
  4031.     textWin << "HTML print canceled." << "\n";
  4032.     return; // No vaild file name
  4033.   }
  4034.   
  4035.   UString sbuf;
  4036.   
  4037.   if(VBDFile::Exists(FileName)) {
  4038.     sbuf = sbuf + "The " + FileName + " file already exists!\nOverwrite it?";
  4039.     yn = wxMessageBox(sbuf.c_str(), "File Exists", wxYES_NO|wxCENTRE);
  4040.  
  4041.     if(yn == wxNO) {
  4042.       textWin << "HTML print canceled." << "\n";
  4043.       return;
  4044.     }
  4045.   }
  4046.   
  4047.   ofstream stream(FileName, ios::out); // Open file and truncate it
  4048.   textWin << "Printing to: " << FileName << "\n";
  4049.   
  4050.   if(!stream) { // Could not open the stream
  4051.     sbuf.DeleteAt(0, sbuf.length());
  4052.     sbuf = sbuf + "Could not write to: " + FileName;
  4053.     textWin << sbuf.c_str() << "\n";
  4054.     Error->Message(sbuf.c_str());
  4055.     return; 
  4056.   }
  4057.           
  4058.   HyperText htm(stream);
  4059.   char date[255]; htm.GetSystemTime(date);
  4060.   htm << comment << "HTML file generated by: " << ProgramName << " version ";
  4061.   htm.precision(3);
  4062.   htm << VersionNumber << ecomment << endl;
  4063.   htm << comment << "File Creation date: " << date << ecomment << endl;
  4064.  
  4065.   htm.Prologue(ProgramName);
  4066.   htm.StartBody("BGCOLOR=\"#FFFFFF\"");
  4067.   htm.eat_space(); // Use non-breaking spaces
  4068.   htm.GenTable();
  4069.   int num_columns = 0;
  4070.  
  4071.   // Calculate the number of columns
  4072.   if(KeyName != 0) num_columns++; 
  4073.   if(M2Name != 0) num_columns++; 
  4074.   if(M3Name != 0) num_columns++; 
  4075.   if(M4Name != 0) num_columns++; 
  4076.   if(M5Name != 0) num_columns++; 
  4077.   if(M6Name != 0) num_columns++; 
  4078.   if(M7Name != 0) num_columns++; 
  4079.   if(M8Name != 0) num_columns++; 
  4080.   if(Comments != 0) num_columns++;
  4081.  
  4082.   // Write the table title
  4083.   htm.StartTableRow();
  4084.   htm.TableHeader("CENTER", num_columns, 1, 10);
  4085.   char sys_time[255];
  4086.   htm.GetSystemTime(sys_time);
  4087.   htm << ' ' << ProgramName << ' ' << br << ' ' << sys_time << ' ';
  4088.   htm.EndTableHeader();
  4089.   htm.EndTableRow();
  4090.   
  4091.   // Write the table headers
  4092.   htm.StartTableRow();
  4093.   if(KeyName != 0) {
  4094.     htm.TableHeader();
  4095.     htm << ' ' << KeyName << ' ';
  4096.     htm.EndTableHeader();
  4097.   } 
  4098.   if(M2Name != 0) {
  4099.     htm.TableHeader();
  4100.     htm << ' ' << M2Name << ' ';
  4101.     htm.EndTableHeader();
  4102.   }
  4103.   if(M3Name != 0) {
  4104.     htm.TableHeader();
  4105.     htm << ' ' << M3Name << ' ';
  4106.     htm.EndTableHeader();
  4107.   }
  4108.   if(M4Name != 0) {
  4109.     htm.TableHeader();
  4110.     htm << ' ' << M4Name << ' ';
  4111.     htm.EndTableHeader();
  4112.   }
  4113.   if(M5Name != 0) {
  4114.     htm.TableHeader();
  4115.     htm << ' ' << M5Name << ' ';
  4116.     htm.EndTableHeader();
  4117.   }
  4118.   if(M6Name != 0) {
  4119.     htm.TableHeader();
  4120.     htm << ' ' << M6Name << ' ';
  4121.     htm.EndTableHeader();
  4122.   }
  4123.   if(M7Name != 0) {
  4124.     htm.TableHeader();
  4125.     htm << ' ' << M7Name << ' ';
  4126.     htm.EndTableHeader();
  4127.   }
  4128.   if(M8Name != 0) {
  4129.     htm.TableHeader();
  4130.     htm << ' ' << M8Name << ' ';
  4131.     htm.EndTableHeader();
  4132.   }
  4133.   if(Comments != 0) {
  4134.     htm.TableHeader();
  4135.     htm << ' ' << Comments << ' ';
  4136.     htm.EndTableHeader();
  4137.   }
  4138.   htm.EndTableRow();
  4139.   
  4140.   StrDB strdb(DB);
  4141.   dllistptr = dllist->GetFront();
  4142.   textWin << "Printing..." << "\n";
  4143.  
  4144.   while(!dllist->IsHeader(dllistptr)) {
  4145.     strdb.ReadObject(dllistptr->Data.object_address);
  4146.     htm.StartTableRow();
  4147.     if(KeyName != 0) {
  4148.       htm.TableData();
  4149.       htm << strdb.GetKM();
  4150.       htm.EndTableData();
  4151.     } 
  4152.     if(M2Name != 0) {
  4153.       htm.TableData();
  4154.       htm << strdb.GetM2() << ' ';
  4155.       htm.EndTableData();
  4156.     }
  4157.     if(M3Name != 0) {
  4158.       htm.TableData();
  4159.       htm << strdb.GetM3() << ' ';
  4160.       htm.EndTableData();
  4161.     }
  4162.     if(M4Name != 0) {
  4163.       htm.TableData();
  4164.       htm << strdb.GetM4() << ' ';
  4165.       htm.EndTableData();
  4166.     }
  4167.     if(M5Name != 0) {
  4168.       htm.TableData();
  4169.       htm << strdb.GetM5() << ' ';
  4170.       htm.EndTableData();
  4171.     }
  4172.     if(M6Name != 0) {
  4173.       htm.TableData();
  4174.       htm << strdb.GetM6() << ' ';
  4175.       htm.EndTableData();
  4176.     }
  4177.     if(M7Name != 0) {
  4178.       htm.TableData();
  4179.       htm << strdb.GetM7() << ' ';
  4180.       htm.EndTableData();
  4181.     }
  4182.     if(M8Name != 0) {
  4183.       htm.TableData();
  4184.       htm << strdb.GetM8() << ' ';
  4185.       htm.EndTableData();
  4186.     }
  4187.     if(Comments != 0) {
  4188.       htm.TableData();
  4189.       htm << strdb.GetCM() << ' ';
  4190.       htm.EndTableData();
  4191.     }
  4192.     htm.EndTableRow();
  4193.     dllistptr = dllistptr->GetNext();
  4194.   }
  4195.  
  4196.   htm.EndTable();
  4197.   htm.Epilogue();
  4198.   
  4199.   textWin << "Finished." << "\n";
  4200.   stream.close();
  4201. }
  4202. // ----------------------------------------------------------- //
  4203. // ------------------------------- //
  4204. // --------- End of File --------- //
  4205. // ------------------------------- //
  4206.  
  4207.